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 相关文章推荐
JS this作用域以及GET传输值过长的问题解决方法
Aug 06 Javascript
父页面显示遮罩层弹出半透明状态的dialog
Mar 04 Javascript
Bootstrap基本样式学习笔记之标签(5)
Dec 07 Javascript
ES6实现的遍历目录函数示例
Apr 07 Javascript
javascript 开发之网页兼容各种浏览器
Sep 28 Javascript
vue 组件中添加样式不生效的解决方法
Jul 06 Javascript
Node.js+ELK日志规范的实现
May 23 Javascript
微信小程序地图绘制线段并且测量(实例代码)
Jan 02 Javascript
Vue学习之常用指令实例详解
Jan 06 Javascript
Vue列表循环从指定下标开始的多种解决方案
Apr 08 Javascript
vue+element获取el-table某行的下标,根据下标操作数组对象方式
Aug 07 Javascript
详解如何使用React Hooks请求数据并渲染
Oct 18 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
php array的学习笔记
2012/05/10 PHP
Laravel框架中扩展函数、扩展自定义类的方法
2014/09/04 PHP
[原创]解决wincache不支持64位PHP5.5/5.6的问题(提供64位wincache下载)
2016/06/22 PHP
PHP基于方差和标准差计算学生成绩的稳定性示例
2017/07/04 PHP
PHP+RabbitMQ实现消息队列的完整代码
2019/03/20 PHP
javascript FormatNumber函数实现方法
2008/12/30 Javascript
网页收藏夹显示ICO图标(代码少)
2015/08/04 Javascript
JavaScript动态生成二维码图片
2016/04/20 Javascript
使用 NodeJS+Express 开发服务端的简单介绍
2017/04/07 NodeJs
[02:08]DOTA2英雄基础教程 马格纳斯
2014/01/17 DOTA
[01:01:25]DOTA2上海特级锦标赛B组资格赛#2 Fnatic VS Spirit第三局
2016/02/27 DOTA
收集的几个Python小技巧分享
2014/11/22 Python
Python HTMLParser模块解析html获取url实例
2015/04/08 Python
python统计文本字符串里单词出现频率的方法
2015/05/26 Python
利用Django内置的认证视图实现用户密码重置功能详解
2017/11/24 Python
python机器人行走步数问题的解决
2018/01/29 Python
python基础教程项目三之万能的XML
2018/04/02 Python
Python实现确认字符串是否包含指定字符串的实例
2018/05/02 Python
Django添加sitemap的方法示例
2018/08/06 Python
Python给图像添加噪声具体操作
2019/03/03 Python
python生成器推导式用法简单示例
2019/10/08 Python
Python进程,多进程,获取进程id,给子进程传递参数操作示例
2019/10/11 Python
如何基于Python实现自动扫雷
2020/01/06 Python
python实现高斯投影正反算方式
2020/01/17 Python
python异常处理之try finally不报错的原因
2020/05/18 Python
python框架flask入门之路由及简单实现方法
2020/06/07 Python
Selenium获取登录Cookies并添加Cookies自动登录的方法
2020/12/04 Python
Julep官网:美容产品和指甲油
2017/02/25 全球购物
俄语翻译实习生的自我评价分享
2013/11/06 职场文书
工程专业毕业生自荐信范文
2013/12/25 职场文书
服装采购员岗位职责
2014/03/15 职场文书
毕业生就业推荐表自我鉴定
2014/03/20 职场文书
单位作风建设自查报告
2014/10/23 职场文书
先进个人推荐材料
2014/12/29 职场文书
七年级思品教学反思
2016/02/20 职场文书
大学生军训心得体会5篇
2019/08/15 职场文书