使用p5.js实现动态GIF图片临摹重现


Posted in Javascript onOctober 23, 2019

前言

根据互动媒体技术老师的实验要求,临摹了一张GIF动态图,使用p5.js进行重现。
博客里面会有实现逻辑以及实现代码,在最后还会有一张自己实现的扩展图。

原图

使用p5.js实现动态GIF图片临摹重现

实现步骤

规律总结

1、观察图片可以看到,整个图是由两个部分组成的,其中一个是棍状体,一个是螺旋状体。

2、棍状体从外到内越来越窄,整个图形在做绕固定旋转圆心的匀速圆周运动。

3、螺旋状体也是在做绕固定旋转圆心的匀速圆周运动。

4、螺旋状体的旋转角速度比棍状体的旋转角速度大。

具体实现逻辑

为了方便分析,我截取了一个静态的瞬间:

使用p5.js实现动态GIF图片临摹重现

那么怎么实现呢?

我们可以创建两个函数,分别实现棍状体和螺旋体,然后再在draw()函数里面去实现这两个函数即可。

这是棍状体的实现函数:

//圆周运动棍状体绘制函数
function drawBoll(r, g, b, interval)

这是螺旋体的实现函数:

//圆周运动螺旋体的绘制函数
function drawBoll2( r, g, b, interval)

分两个部分来讲:

1、棍状体:其实很简单,我们可以看到静止的棍状体就是由14个小圆形组成的,由外到里半径逐渐减小,然后颜色是赤橙黄绿青蓝紫,赤橙黄绿青蓝紫,每个圆形做的是绕固定圆心的匀速圆周运动。那么,我们的实现就是可以先做一个圆形的匀速圆周运动,其他的圆形,只需要修改一下旋转半径、圆形半径以及颜色就可以了。至于圆周运动怎么实现,我会在后面讲到,往后面看就可以了。

2、螺旋体:螺旋体其实也是一个圆形的重复变换得来的,可以看到的是,螺旋体的每个圆形都一样大,不一样的是什么呢?圆形的颜色和旋转半径,还有的就是他们初始就存在的弧度间隔。那么,我们要做的其实就是画出一个匀速圆周运动的圆形,其它的就可以通过修改参数达到目的。

3、最后一步就是在draw()函数中去实现,我使用了一个for循环去实现:

for (var i =1;i < 15; i++) // for循环实现变化的重复
 {
  //其中前三个参数是颜色的RGB值,最后一个参数i实现各个圆形之间的变化
  drawBoll(139, 0, 255, i); 
  drawBoll2(139, 0, 255, i); 
  i++;
  drawBoll(0, 0, 255, i); 
  drawBoll2(0, 0, 255, i); 
  i++;
  drawBoll(0, 255, 255, i); 
  drawBoll2(0, 255, 255, i); 
  i++;
  drawBoll(0, 255, 0, i); 
  drawBoll2(0, 255, 0, i);
  i++;
  drawBoll(255, 255, 0, i); 
  drawBoll2(255, 255, 0, i); 
  i++;
  drawBoll(255, 165, 0, i); 
  drawBoll2(255, 165, 0, i); 
  i++;
  drawBoll(255, 0, 0, i); 
  drawBoll2(255, 0, 0, i); 
 }

代码实现

关于这个程序,具体的p5.js代码在这里:

//准备画板
function setup() {
 createCanvas(1000, 1000);
}

//开始作画
function draw() {
 background(50); //背景颜色
 for (var i =1;i < 15; i++) // for循环实现变化的重复
 {
  //其中前三个参数是颜色的RGB值,最后一个参数i实现各个圆形之间的变化
  drawBoll(139, 0, 255, i); 
  drawBoll2(139, 0, 255, i); 
  i++;
  drawBoll(0, 0, 255, i); 
  drawBoll2(0, 0, 255, i); 
  i++;
  drawBoll(0, 255, 255, i); 
  drawBoll2(0, 255, 255, i); 
  i++;
  drawBoll(0, 255, 0, i); 
  drawBoll2(0, 255, 0, i);
  i++;
  drawBoll(255, 255, 0, i); 
  drawBoll2(255, 255, 0, i); 
  i++;
  drawBoll(255, 165, 0, i); 
  drawBoll2(255, 165, 0, i); 
  i++;
  drawBoll(255, 0, 0, i); 
  drawBoll2(255, 0, 0, i); 
 }
}

//圆周运动棍状体绘制函数
function drawBoll(r, g, b, interval){
 fill(r, g, b);
 var x = 500; //圆周运动圆心的x坐标
 var y = 500; //圆周运动圆心的y坐标
 var t = millis() / 3; // 控制旋转速度的参数
 var xChange //圆周运动x坐标变化值
 var yChange; //圆周运动y坐标变化值
 var radius = interval * 15;//圆周运动的半径
 xChange = radius * Math.cos(t * Math.PI/180);
 yChange = radius * Math.sin(t * Math.PI/180); 
 x += xChange;
 y += yChange;
 ellipse(x, y, interval * 5, interval * 5);
}

//圆周运动螺旋体的绘制函数
function drawBoll2( r, g, b, interval){
 fill(r, g, b);
 var x = 500; //圆周运动圆心的x坐标
 var y = 500; //圆周运动圆心的y坐标
 var t = millis() / 1 + interval * 24; //24是两个小球之间间隔的角度
 var xChange //圆周运动x坐标变化值
 var yChange; //圆周运动y坐标变化值
 var radius = interval * 15;//圆周运动的半径
 xChange = radius * Math.cos(t * Math.PI/180);
 yChange = radius * Math.sin(t * Math.PI/180); 
 x += xChange;
 y += yChange;
 ellipse(x, y, 30, 30);
}

遇到的问题以及解决方案

1、怎样实现匀速圆周运动?

接着上面说的,怎么实现匀速圆周运动呢?

关于匀速圆周运动,要实现的话:
首先,我们要知道他的旋转半径、旋转圆心以及旋转角速度。
其次,就是根据这些参数,利用三角函数,去计算出运动的点的坐标与旋转圆心坐标之间的差。
最后,就是将圆心坐标补上这个计算出来的差,算出圆周运动的各个点的坐标,以这些坐标为圆心画小圆,这些小圆就是我们要的圆形了。

匀速圆周运动具体代码:

var x = 500; //圆周运动圆心的x坐标
 var y = 500; //圆周运动圆心的y坐标
 var t = millis() / 3; // 控制旋转速度的参数
 var xChange //圆周运动x坐标变化值
 var yChange; //圆周运动y坐标变化值
 var radius = interval * 15;//圆周运动的半径
 xChange = radius * Math.cos(t * Math.PI/180);
 yChange = radius * Math.sin(t * Math.PI/180); 
 x += xChange;
 y += yChange;
 ellipse(x, y, interval * 5, interval * 5);

2、p5.js与之前接触的编程语言的一些不同

一个是在p5.js中写函数的时候,括号里面的形参不需要声明,举个例子吧:

function drawBoll(r, g, b, interval)

上面这个就是正确的示例,下面是错误的例子:

function drawBoll(var r, var g, var b, var interval)

也就是说,形参里面不可以写var声明,不然会报错。

还有一个就是p5.js中声明变量用 var 就可以了,不要用int, char, string这些。

结果图

使用p5.js实现动态GIF图片临摹重现

扩展作品

使用p5.js实现动态GIF图片临摹重现

扩展作品介绍

这是我的扩展作品,是一个时钟,加上一个鼠标的交互

中间的分别是时针,分针,秒针,他们的实现就和上面那个gif图中的棍状体的实现一样,改了一下角速度和圆形大小。改了 参数而已,我就不再细说。

主要来介绍一下这个简单的鼠标交互事件。

关于交互的话,可以看到的是这个律动的心是由两个部分组成的。

一个部分是外围的律动的粉色圆形,通过ellipse函数,这个圆形的圆心坐标就是当前鼠标的坐标,宽和高是变化的,我们可以设置一个变量size,size不断变大,到达临界值就减少,然后继续增大就可以了,代码如下:

size = size + 3;
if (size > 50)
  size = 20;
 ellipse(mouseX, mouseY, 20+size, 20+size);

一个部分就是中间的爱心,爱心是三个半圆组成,上面是两个小半圆,下面是一个大半圆,律动的效果和上面的一样。代码如下:

size = size + 3;
if (size > 50)
  size = 20;
 fill(255,0,0);//红色
 arc(mouseX+size/4, mouseY, size/2, size/2, PI, 0);//半圆
 arc(mouseX-size/4, mouseY, size/2, size/2, PI, 0);//半圆
 arc(mouseX, mouseY, size, size, 0*PI, 1*PI);//半圆

具体代码实现

//准备画板
function setup() {
 createCanvas(1000, 1000);
}

//开始作画
function draw() {
 background(50); //背景颜色
 for (var i =1;i < 15; i++) // for循环实现变化的重复
 {
  //其中前三个参数是颜色的RGB值,最后一个参数i实现各个圆形之间的变化
  drawBoll(139, 0, 255, i); 
  drawBoll2(139, 0, 255, i); 
  drawBoll3(139, 0, 255, i); 
  i++;
  drawBoll(0, 0, 255, i); 
  drawBoll2(0, 0, 255, i); 
  drawBoll3(0, 0, 255, i); 
  i++;
  drawBoll(0, 255, 255, i); 
  drawBoll2(0, 255, 255, i); 
  drawBoll3(0, 255, 255, i); 
  i++;
  drawBoll(0, 255, 0, i); 
  drawBoll2(0, 255, 0, i);
  drawBoll3(0, 255, 0, i);
  i++;
  drawBoll(255, 255, 0, i); 
  drawBoll2(255, 255, 0, i); 
  drawBoll3(255, 255, 0, i); 
  i++;
  drawBoll(255, 165, 0, i); 
  drawBoll2(255, 165, 0, i); 
  drawBoll3(255, 165, 0, i); 
  i++;
  drawBoll(255, 0, 0, i); 
  drawBoll2(255, 0, 0, i); 
  drawBoll3(255, 0, 0, i); 
 }
 mouse(255, 192, 203);
}

//时针绘制函数
function drawBoll(r, g, b, interval){
 fill(r, g, b);
 var x = 500; //圆周运动圆心的x坐标
 var y = 500; //圆周运动圆心的y坐标
 var t = 6 * millis() / 3600000; // 控制旋转速度的参数
 var xChange //圆周运动x坐标变化值
 var yChange; //圆周运动y坐标变化值
 var radius = interval * 15;//圆周运动的半径
 xChange = radius * Math.cos(t * Math.PI/180 - Math.PI / 2);
 yChange = radius * Math.sin(t * Math.PI/180 - Math.PI / 2); 
 x += xChange;
 y += yChange;
 ellipse(x, y, 30, 30);
}

//分针绘制函数
function drawBoll2( r, g, b, interval){
 fill(r, g, b);
 var x = 500; //圆周运动圆心的x坐标
 var y = 500; //圆周运动圆心的y坐标
 var t = 6 * millis() / 60000; // 控制旋转速度的参数
 var xChange //圆周运动x坐标变化值
 var yChange; //圆周运动y坐标变化值
 var radius = interval * 15;//圆周运动的半径
 xChange = radius * Math.cos(t * Math.PI/180 - Math.PI / 2);
 yChange = radius * Math.sin(t * Math.PI/180 - Math.PI / 2); 
 x += xChange;
 y += yChange;
 ellipse(x, y, 20, 20);
}

//秒针绘制函数
function drawBoll3( r, g, b, interval){
 fill(r, g, b);
 var x = 500; //圆周运动圆心的x坐标
 var y = 500; //圆周运动圆心的y坐标
 var t = 6 * millis() / 1000; // 控制旋转速度的参数
 var xChange //圆周运动x坐标变化值
 var yChange; //圆周运动y坐标变化值
 var radius = interval * 15;//圆周运动的半径
 xChange = radius * Math.cos(t * Math.PI/180 - Math.PI / 2);
 yChange = radius * Math.sin(t * Math.PI/180 - Math.PI / 2); 
 x += xChange;
 y += yChange;
 ellipse(x, y, 10, 10);
}

var size = 0;
// 实现鼠标交互的函数(律动的爱心)
function mouse(r, g, b){
 fill(r, g, b);
 size = size + 3;
 if (size > 50)
  size = 20;
 ellipse(mouseX, mouseY, 20+size, 20+size);
 fill(255,0,0);//红色
 arc(mouseX+size/4, mouseY, size/2, size/2, PI, 0);//半圆
 arc(mouseX-size/4, mouseY, size/2, size/2, PI, 0);//半圆
 arc(mouseX, mouseY, size, size, 0*PI, 1*PI);//半圆
}

以上便是此次实验的全部内容。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jquery 插件之仿“卓越亚马逊”首页弹出菜单效果
Dec 25 Javascript
jquery调用wcf并展示出数据的方法
Jul 07 Javascript
jQuery简易图片放大特效示例代码
Jun 09 Javascript
js实现简单随机抽奖的方法
Jan 27 Javascript
WordPress 单页面上一页下一页的实现方法【附代码】
Mar 10 Javascript
vue基于Vue2.0和高德地图的地图组件实例
Apr 28 Javascript
ReactJS实现表单的单选多选和反选的示例
Oct 13 Javascript
JS和Canvas实现图片的预览压缩和上传功能
Mar 30 Javascript
vue2.0 中使用transition实现动画效果使用心得
Aug 13 Javascript
axios携带cookie配置详解(axios+koa)
Dec 28 Javascript
微信小程序 拍照或从相册选取图片上传代码实例
Aug 28 Javascript
微信小程序基于ColorUI构建皮皮虾短视频去水印组件
Nov 04 Javascript
p5.js临摹动态图形的方法
Oct 23 #Javascript
Vue 实现点击空白处隐藏某节点的三种方式(指令、普通、遮罩)
Oct 23 #Javascript
p5.js实现动态图形临摹
Oct 23 #Javascript
浅析webpack-bundle-analyzer在vue-cli3中的使用
Oct 23 #Javascript
微信小程序 生成携带参数的二维码
Oct 23 #Javascript
使用p5.js临摹动态图形
Oct 23 #Javascript
浅析vue-cli3配置webpack-bundle-analyzer插件【推荐】
Oct 23 #Javascript
You might like
比较全的PHP 会话(session 时间设定)使用入门代码
2008/06/05 PHP
PHP安全防范技巧分享
2011/11/03 PHP
ThinkPHP自动完成中使用函数与回调方法实例
2014/11/29 PHP
Yii框架在页面输出执行sql语句以方便调试的实现方法
2014/12/24 PHP
PHP构造二叉树算法示例
2017/06/21 PHP
jQuery的实现原理的模拟代码 -1 核心部分
2010/08/01 Javascript
JQuery实现倒计时按钮的实现代码
2012/03/23 Javascript
js中的时间转换—毫秒转换成日期时间的示例代码
2014/01/26 Javascript
基于Flowplayer打造一款免费的WEB视频播放器附源码
2015/09/06 Javascript
微信小程序 页面跳转及数据传递详解
2017/03/14 Javascript
微信小程序 滚动到某个位置添加class效果实现代码
2017/04/19 Javascript
vue.js前后端数据交互之提交数据操作详解
2018/04/24 Javascript
Angular动态绑定样式及改变UI框架样式的方法小结
2018/09/03 Javascript
详解CommonJS和ES6模块循环加载处理的区别
2018/12/26 Javascript
分享一个vue项目“脚手架”项目的实现步骤
2019/05/26 Javascript
vue实现路由监听和参数监听
2019/10/29 Javascript
echarts实现折线图的拖拽效果
2019/12/19 Javascript
JS+CSS实现过渡特效
2021/01/02 Javascript
Python打包文件夹的方法小结(zip,tar,tar.gz等)
2016/09/18 Python
Python递归实现汉诺塔算法示例
2018/03/19 Python
Python实现按中文排序的方法示例
2018/04/25 Python
Sanic框架请求与响应实例分析
2018/07/16 Python
Python实现的逻辑回归算法示例【附测试csv文件下载】
2018/12/28 Python
Python短信轰炸的代码
2020/03/25 Python
基于K.image_data_format() == 'channels_first' 的理解
2020/06/29 Python
python 密码学示例——理解哈希(Hash)算法
2020/09/21 Python
HTML5自定义data-* data(obj)属性和jquery的data()方法的使用
2012/12/13 HTML / CSS
SteelSeries赛睿官网:游戏外设和配件的领先制造商(耳机、键盘、鼠标和鼠标垫)
2018/06/17 全球购物
Tirendo比利时:在线购买轮胎
2018/10/22 全球购物
圣彼得堡鲜花配送:Semicvetic
2020/09/15 全球购物
英国时尚首饰品牌:Missoma
2020/06/29 全球购物
建筑工程技术应届生自荐信
2013/09/27 职场文书
应聘医药销售自荐书范文
2014/02/08 职场文书
高中生操行评语大全
2014/04/25 职场文书
个人对照检查剖析材料
2014/10/13 职场文书
2015年端午节国旗下演讲稿
2015/03/19 职场文书