使用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 相关文章推荐
Javascript MD4
Dec 20 Javascript
如何使用Jquery获取Form表单中被选中的radio值
Aug 09 Javascript
jQuery.each使用详解
Jul 07 Javascript
理解javascript中的原型和原型链
Jul 30 Javascript
javascript中eval解析JSON字符串
Feb 27 Javascript
jQuery中队列queue()函数的实例教程
May 03 Javascript
使用AJAX实现Web页面进度条的实例分享
May 06 Javascript
JavaScript sort数组排序方法和自我实现排序方法小结
Jun 06 Javascript
jQuery实现动态加载select下拉列表项功能示例
May 31 jQuery
微信小程序实现下拉菜单切换效果
Mar 30 Javascript
vue使用高德地图点击下钻上浮效果的实现思路
Oct 12 Javascript
详解react组件通讯方式(多种)
May 06 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
JS 网站性能优化笔记
2011/05/24 PHP
PHP实现生成推广海报的方法详解
2018/03/14 PHP
PhpStorm+xdebug+postman调试技巧分享
2020/09/15 PHP
JQuery UI的拖拽功能实现方法小结
2012/03/14 Javascript
js加强的经典分页实例
2013/03/15 Javascript
浅析LigerUi开发中谨慎载入common.css文件
2013/07/09 Javascript
javascript实现简单的鼠标拖动效果实例
2015/04/10 Javascript
js从数组中删除指定值(不是指定位置)的元素实现代码
2016/09/13 Javascript
用js写的一个路由(简单实例)
2016/09/24 Javascript
Angular2使用Guard和Resolve进行验证和权限控制
2017/04/24 Javascript
addeventlistener监听scroll跟touch(实例讲解)
2017/08/04 Javascript
MUI 实现侧滑菜单及其主体部分上下滑动的方法
2018/01/25 Javascript
解决IE11 vue +webpack 项目中数据更新后页面没有刷新的问题
2018/09/25 Javascript
解决echarts的多个折现数据出现坐标和值对不上的问题
2018/12/28 Javascript
vue实现在线预览pdf文件和下载(pdf.js)
2019/11/26 Javascript
JavaScript进制转换实现方法解析
2020/01/18 Javascript
JS运算符简单用法示例
2020/01/19 Javascript
Python的Django应用程序解决AJAX跨域访问问题的方法
2016/05/31 Python
python itchat实现微信自动回复的示例代码
2017/08/14 Python
利用Python2下载单张图片与爬取网页图片实例代码
2017/12/25 Python
python使用turtle绘制分形树
2018/06/22 Python
Pycharm更换python解释器的方法
2018/10/29 Python
python获取中文字符串长度的方法
2018/11/14 Python
Python日志无延迟实时写入的示例
2019/07/11 Python
python/Matplotlib绘制复变函数图像教程
2019/11/21 Python
Python SSL证书验证问题解决方案
2020/01/13 Python
通过canvas转换颜色为RGBA格式及性能问题的解决
2019/11/22 HTML / CSS
介绍一下结构化程序设计方法和面向对象程序设计方法的区别
2012/06/27 面试题
金额转换,阿拉伯数字的金额转换成中国传统的形式如:(¥1011)-> (一千零一拾一元整)输出
2015/05/29 面试题
幼儿园教师自我鉴定
2014/03/20 职场文书
小学师德师风演讲稿
2014/09/02 职场文书
五好家庭申报材料
2014/12/20 职场文书
客户答谢会致辞
2015/01/20 职场文书
2015年中职班主任工作总结
2015/05/25 职场文书
学会Python数据可视化必须尝试这7个库
2021/06/16 Python
Android开发之底部导航栏的快速实现
2022/04/28 Java/Android