p5.js临摹旋转爱心


Posted in Javascript onOctober 23, 2019

运用p5.js临摹旋转爱心,供大家参考,具体内容如下

原图

我的临摹

效果不错的样子,让我们看看实现过程。

第一步、分析原图GIF

因为原图中旋转速度较快,无法用肉眼直观地找到规律。所以我把gif分解,共90帧,一帧一帧的寻找旋转规律。

从上往下顺序,第一层到第六层。从简单的说起。
第六层:逆时针匀速旋转一圈。
第五层:先逆时针旋转α,速度由v1变为0。再顺时针旋转180°+2α,速度由0变为v2,再变为0。最后逆时针旋转α,速度由0变为v1。(观察原图,我将α设为30°0)
第四层:先逆时针旋转α,再顺时针旋转3×180°+2α,最后逆时针旋转α。速度规律与第五层相同。
第三层:先逆时针旋转α,再顺时针旋转5×180°+2α,最后逆时针旋转α。速度规律与第五层相同。
第二层:先逆时针旋转α,再顺时针旋转7×180°+2α,最后逆时针旋转α。速度规律与第五层相同。
第一层:先逆时针旋转α,再顺时针旋转9×180°+2α,最后逆时针旋转α。速度规律与第五层相同。
(注:使用时记得转化为弧度制。)

第二步、绘制基本形状

首先创建画布,设置背景色

function setup() {
  createCanvas(windowWidth, windowHeight,WEBGL);
}

function draw() {
background(220);
}

绘制第一层立方体

值得注意的是translate()函数使用的是偏移量,而不是坐标值。

function drawHeart1(BoxSize,posX,posY,posZ,r,g,b)  //第一排方块
{
fill(r,g,b);
translate(posX-(10/9)*BoxSize,posY,posZ);
box(BoxSize);
translate(-(10/9)*BoxSize,0,0);
box(BoxSize);
translate(3*(10/9)*BoxSize,0,0);
box(BoxSize);
translate((10/9)*BoxSize,0,0);
box(BoxSize);
translate(0,0,(10/9)*BoxSize);
box(BoxSize);
translate(-(10/9)*BoxSize,0,0);
box(BoxSize);
translate(-2*(10/9)*BoxSize,0,0);
box(BoxSize);
translate(-(10/9)*BoxSize,0,0);
box(BoxSize);
}

在draw()函数中,添加代码。
drawHearts()中第一个参数是立方体的边长,第二到第四个参数是XYZ轴的偏移量,最后三个为立方体颜色RGB值。

push();
translate(0,0);
drawHeart1(40*size1,0,-2*40*10/9,-20,251,68,104);
pop();

以此类推画出其余五层的立方体。

效果图如上(此处调整了一下相机位置)

第三步、旋转

在之前绘制每一层时,要注意物体的X、Z为0,因为rotateY()函数绕Y轴旋转,否则每一层在旋转时不是以绕其中心旋转。

第六层的旋转

①设置旋转角度变量

②在draw()函数中关于第六层代码。其中theta6-=360*PI/180/90表示一帧旋转的弧度增量。

 /></p>
<p>第五层的旋转</p>
<p>①设置旋转角度变量</p>
<p><img/resources/imgs/img_not_found.png

②在draw()函数中关于第五层代码。

③RotateCubes5()函数。第一个参数表示逆时针旋转角度,第二个参数表示顺时针旋转角度的二分之一,第四、五、六个参数用来判断旋转时帧的范围,并用于计算旋转角度。
以第一个if语句为例
在第一帧到第f1帧时,theta5减小,即实现逆时针绕Y轴旋转。其中,frameCount表示当前第几帧。frameCount%90,因为原图有90帧。(f1-frameCount%90)* delta1 * PI *180/Summation(0,f1-1)实现1到f1范围内当前帧数越大,旋转弧度越小。

function RotateCubes5(delta1,delta2,f1,f2,f3){
 if(frameCount%90>=1&&frameCount%90<=f1)
 {
 theta5-=(f1-frameCount%90)*delta1*PI/180/Summation(0,f1-1); 
 }
 if(frameCount%90>=f1+1&&frameCount%90<=f2)
 {
 theta5+=(frameCount%90-f1-1)*delta2*PI/180/Summation(0,f2-f1-1);
 }
 if(frameCount%90>=f2+1&&frameCount%90<=f3)
 {
 theta5+=(f3-frameCount%90)*delta2*PI/180/Summation(0,f2-f1-1);
 }
 if(frameCount%90>=f3+1&&frameCount%90<=89)
 {
 theta5-=(frameCount%90-f3-1)*delta1*PI/180/Summation(0,f1-1);
 }
 if(frameCount%90==0)
 {
    theta5-=(90-f3-1)*delta1*PI/180/Summation(0,f1-1);
 }
  return theta5;
}

③Summation()函数,即高斯求和。

function Summation(n1,n2)
{
 return (n1+n2)*(n2-n1+1)/2;
}

第一到四层的旋转
第一到四层的旋转与第五层一致,修改传入参数即可。
其实RotateCubes()的内容是一致的,最后返回一个theta。但当我为theta赋值后return(如下图),产生效果发生错误 ,分配数据发生错误。第一次接触p5.js,感觉代码写得比较冗余,后续学习中优化。

以上,即完成了对原图的临摹。

拓展作品

让立方体的大小随帧数变化,90帧一循环。

随帧数增加,深粉立方体变小,浅粉立方体变大。并在一瞬间,深粉立方体和浅粉立方体大小相同,形成一个完整的爱心。

if(frameCount%200>=0&&frameCount%200<=99)  //扩展作品2
{
 size1=frameCount%100*0.02;      
  size2=(100-frameCount%100)*0.02;
  size3=frameCount%100*0.02;
  size4=(100-frameCount%100)*0.02;
  size5=frameCount%100*0.02;
  size6=(100-frameCount%100)*0.02;
}
if(frameCount%200>=100&&frameCount%200<=199)
{     
  size1=(100-frameCount%100)*0.02;
  size2=frameCount%100*0.02;
  size3=(100-frameCount%100)*0.02;
  size4=frameCount%100*0.02;
  size5=(100-frameCount%100)*0.02;
  size6=frameCount%100*0.02; 
}

体会:

三维图形比起二维图像要多一个z参数,所以在排布位置的时候难度增大,且translate()函数的参数是偏移量,又为图形绘制增加了难度。

本GIF又一难点在于运动规律不能用肉眼直接获得,需要把GIF分解到每一帧,逐帧观察。运动规律相对复杂,且每一层运动规律都不同,需要控制的变量较多。

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

Javascript 相关文章推荐
JavaScript快速检测浏览器对CSS3特性的支持情况
Sep 26 Javascript
使用Jquery获取带特殊符号的ID 标签的方法
Apr 30 Javascript
php读取sqlite数据库入门实例代码
Jun 25 Javascript
实例解析jQuery中proxy()函数的用法
May 24 Javascript
在Javascript操作JSON对象,增加 删除 修改的简单实现
Jun 02 Javascript
Js 获取、判断浏览器版本信息的简单方法
Aug 08 Javascript
利用React-router+Webpack快速构建react程序
Oct 27 Javascript
Centos6.8下Node.js安装教程
May 12 Javascript
详解Vue+ElementUI从零开始搭建自己的网站(一、环境搭建)
Apr 30 Javascript
js实现网页版贪吃蛇游戏
Feb 22 Javascript
Angular8 简单表单验证的实现示例
Jun 03 Javascript
如何使用JS console.log()技巧提高工作效率
Oct 14 Javascript
JavaScript 作用域scope简单汇总
Oct 23 #Javascript
node.js使用fs读取文件出错的解决方案
Oct 23 #Javascript
jquery 键盘事件 keypress() keydown() keyup()用法总结
Oct 23 #jQuery
JavaScript提升机制Hoisting详解
Oct 23 #Javascript
使用p5.js实现动态GIF图片临摹重现
Oct 23 #Javascript
p5.js临摹动态图形的方法
Oct 23 #Javascript
Vue 实现点击空白处隐藏某节点的三种方式(指令、普通、遮罩)
Oct 23 #Javascript
You might like
编写漂亮的代码 - 将后台程序与前端程序分开
2008/04/23 PHP
PHP人民币金额数字转中文大写的函数代码
2013/02/27 PHP
thinkphp框架下实现登录、注册、找回密码功能
2016/04/06 PHP
PHP中通过getopt解析GNU C风格命令行选项
2019/11/18 PHP
javascript 函数调用规则
2009/08/26 Javascript
JavaScript取得鼠标绝对位置程序代码介绍
2012/09/16 Javascript
调用jQuery滑出效果时闪烁的解决方法
2014/03/27 Javascript
jQuery的one()方法用法实例
2015/01/19 Javascript
JavaScript动态修改网页元素内容的方法
2015/03/21 Javascript
详解JavaScript数组的操作大全
2015/10/19 Javascript
javascript模块化简单解析
2016/04/07 Javascript
AngularJS 2.0入门权威指南
2016/10/08 Javascript
对存在JavaScript隐式类型转换的四种情况的总结(必看篇)
2017/08/31 Javascript
用js实现before和after伪类的样式修改的示例代码
2017/09/07 Javascript
swiper 解决动态加载数据滑动失效的问题
2018/02/26 Javascript
vue组件之间通信实例总结(点赞功能)
2018/12/05 Javascript
vue列表单项展开收缩功能之this.$refs的详解
2019/05/05 Javascript
vue中$refs, $emit, $on, $once, $off的使用详解
2019/05/26 Javascript
vue中添加与删除关键字搜索功能
2019/10/12 Javascript
VUE渲染后端返回含有script标签的html字符串示例
2019/10/28 Javascript
[08:06]DOTA2-DPC中国联赛 正赛 PSG.LGD vs Elephant 选手采访
2021/03/11 DOTA
在Python的Flask框架中实现单元测试的教程
2015/04/20 Python
Python的time模块中的常用方法整理
2015/06/18 Python
Python基础教程之正则表达式基本语法以及re模块
2016/03/25 Python
Python中的time模块与datetime模块用法总结
2016/06/30 Python
Python实现查找匹配项作处理后再替换回去的方法
2017/06/10 Python
关于Python中定制类的比较运算实例
2019/12/19 Python
python dumps和loads区别详解
2020/02/04 Python
Python实现捕获异常发生的文件和具体行数
2020/04/25 Python
详解Selenium 元素定位和WebDriver常用方法
2020/12/04 Python
Spartoo英国:欧洲最大的网上鞋店
2016/09/13 全球购物
什么是serialVersionUID
2016/03/04 面试题
祖国在我心中的演讲稿
2014/05/04 职场文书
2014年入党积极分子学习三中全会思想汇报
2014/09/13 职场文书
幼儿园综治宣传月活动总结
2015/05/07 职场文书
工地食品安全责任书
2015/05/09 职场文书