使用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 笔记 事件
Nov 02 Javascript
jqPlot 图表中文API使用文档及源码和在线示例
Feb 07 Javascript
JS中 用户登录系统的解决办法
Apr 15 Javascript
JavaScript文档碎片操作实例分析
Dec 12 Javascript
JavaScript记录光标在编辑器中位置的实现方法
Apr 22 Javascript
第九章之路径分页标签与徽章组件
Apr 25 Javascript
JQuery 传送中文乱码问题的简单解决办法
May 24 Javascript
Angular表单验证实例详解
Oct 20 Javascript
JS控制TreeView的结点选择
Nov 11 Javascript
使用vue-route 的 beforeEach 实现导航守卫(路由跳转前验证登录)功能
Mar 22 Javascript
微信小程序自定义组件实现tabs选项卡功能
Jul 14 Javascript
解决Element中el-date-picker组件不回填的情况
Nov 07 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
基于数据库的在线人数,日访问量等统计
2006/10/09 PHP
php实现无限级分类实现代码(递归方法)
2011/01/01 PHP
如何在php中正确的使用json
2013/08/06 PHP
PHP截取发动短信内容的方法
2017/07/04 PHP
PHP实现字符串大小写转函数的功能实例
2019/02/06 PHP
tp5.1 框架join方法用法实例分析
2020/05/26 PHP
javascript利用apply和arguments复用方法
2013/11/25 Javascript
什么是Node.js?Node.js详细介绍
2014/06/01 Javascript
JavaScript 实现的 zip 压缩和解压缩工具包Zip.js使用详解
2015/12/14 Javascript
JS简单循环遍历json数组的方法
2016/04/22 Javascript
jqueryMobile 动态添加元素,展示刷新视图的实现方法
2016/05/28 Javascript
javaScript嗅探执行神器-sniffer.js
2017/02/14 Javascript
微信小程序 开发之滑块视图容器(swiper)详解及实例代码
2017/02/22 Javascript
js定时器+简单的动画效果实例
2017/11/10 Javascript
node打造微信个人号机器人的方法示例
2018/04/26 Javascript
基于JavaScript实现一个简单的Vue
2018/09/26 Javascript
node.js中 redis 的安装和基本操作示例
2020/02/10 Javascript
Javascript如何实现双指控制图片功能
2020/02/25 Javascript
JavaScript, select标签元素左右移动功能实现
2020/05/14 Javascript
js实现批量删除功能
2020/08/27 Javascript
[48:39]Ti4主赛事胜者组第一天 EG vs NEWBEE 2
2014/07/19 DOTA
python获取本机外网ip的方法
2015/04/15 Python
python万年历实现代码 含运行结果
2017/05/20 Python
python 递归深度优先搜索与广度优先搜索算法模拟实现
2018/10/22 Python
Pandas中DataFrame的分组/分割/合并的实现
2019/07/16 Python
深入了解Python 变量作用域
2020/07/24 Python
python工具——Mimesis的简单使用教程
2021/01/16 Python
HTML5 HTMLCollection和NodeList的区别详解
2020/04/29 HTML / CSS
日本高岛屋百货购物网站:TAKASHIMAYA
2019/03/24 全球购物
Perfume’s Club中文官网:西班牙美妆在线零售品牌
2020/08/24 全球购物
如何通过jdbc调用存储过程
2012/04/19 面试题
通信生自我鉴定
2014/01/18 职场文书
文案策划求职信
2014/03/18 职场文书
2014年项目经理工作总结
2014/11/24 职场文书
2019企业文化管理制度范本!
2019/08/06 职场文书
解决mysql问题:由于找不到MSVCR120.dll,无法继续执行代码
2021/06/26 MySQL