使用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 Tips(4) 一些关于提高JQuery性能的Tips
Dec 19 Javascript
关于javascript中的typeof和instanceof介绍
Dec 04 Javascript
JS中怎样判断undefined(比较不错的方法)
Mar 27 Javascript
node.js中的buffer.Buffer.isEncoding方法使用说明
Dec 14 Javascript
js实现简易的单数字随机抽奖(0-9)
Mar 19 Javascript
jQuery实现购物车表单自动结算效果实例
Aug 10 Javascript
详解JavaScript的内置对象
Dec 07 Javascript
Vue全家桶实践项目总结(推荐)
Nov 04 Javascript
使用classList来实现两个按钮样式的切换方法
Jan 24 Javascript
微信小程序结合mock.js实现后台模拟及调试
Mar 28 Javascript
使用 vue 实例更好的监听事件及vue实例的方法
Apr 22 Javascript
vue和小程序项目中使用iconfont的方法
May 19 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 项目的方法
2007/01/02 PHP
php 遍历数据表数据并列表横向排列的代码
2009/09/05 PHP
PHP的serialize序列化数据以及JSON格式化数据分析
2015/10/10 PHP
PHP获取用户客户端真实IP的解决方案
2016/10/10 PHP
php empty 函数判断结果为空但实际值却为非空的原因解析
2018/05/28 PHP
javascript基本语法分析说明
2008/06/15 Javascript
JavaScript中使用replace结合正则实现replaceAll的效果
2010/06/04 Javascript
js过滤数组重复元素的方法
2010/09/05 Javascript
仿微博字符限制效果实现代码
2012/04/20 Javascript
详谈JavaScript 匿名函数及闭包
2014/11/14 Javascript
JavaScript中Number对象的toFixed() 方法详解
2016/09/02 Javascript
vue 实现 tomato timer(蕃茄钟)实例讲解
2017/07/24 Javascript
简单实现js放大镜效果
2017/07/24 Javascript
详解Vue前端对axios的封装和使用
2019/04/01 Javascript
解决vue组件props传值对象获取不到的问题
2019/06/06 Javascript
小程序如何获取多个formId实现详解
2019/09/20 Javascript
js节流防抖应用场景,以及在vue中节流防抖的具体实现操作
2020/09/21 Javascript
基于JS实现操作成功之后自动跳转页面
2020/09/25 Javascript
vue调用微信JSDK 扫一扫,相册等需要注意的事项
2021/01/03 Vue.js
[02:10]2018DOTA2亚洲邀请赛赛前采访-Liquid
2018/04/03 DOTA
运行django项目指定IP和端口的方法
2018/05/14 Python
Python3爬虫全国地址信息
2019/01/05 Python
python基于itchat模块实现微信防撤回
2019/04/29 Python
python调用pyaudio使用麦克风录制wav声音文件的教程
2019/06/26 Python
CSS3提交意见输入框样式代码
2014/10/30 HTML / CSS
图库照片、免版税图片、矢量艺术、视频片段:Depositphotos
2019/08/02 全球购物
Levi’s西班牙官方网站:李维斯,著名的牛仔裤品牌
2020/08/20 全球购物
电气自动化自荐信
2013/10/10 职场文书
军训鉴定表自我鉴定
2014/02/13 职场文书
城市创卫标语
2014/06/17 职场文书
离职感谢信怎么写
2015/01/22 职场文书
丽江古城导游词
2015/02/03 职场文书
英语教师求职信范文
2015/03/20 职场文书
Linux安装Nginx步骤详解
2021/03/31 Servers
MySQL和Oracle批量插入SQL的通用写法示例
2021/11/17 MySQL
Apache Kafka 分区重分配的实现原理解析
2022/07/15 Servers