P5.js
P5.js绘制动态图形
一、实现效果
P5.js是一个JavaScript库,是Processing的Web版本,应用于艺术和设计领域。
二、分析与代码
(1)第一张图片基于P5.js的2D图形,首先分析一下这个动态图的特点:
1.图案完全由3/4圆构成,每个3/4圆的的差异仅仅体现在旋转方向和缺口朝向的位置不同;
2.每行或每列次序为奇数或者偶数的3/4圆旋转方向和缺口朝向相同;
3.相邻两行两列的对应位置的3/4圆的旋转方向和缺口朝向均相反。
根据以上分析,首先实现一个3/4圆的旋转,需要注意的是,为了让图形以自己为中心旋转而不是以原点为中心旋转,需要在rotate()前后增加translate()函数,假设图形中心坐标为(x,y)不同于上次用过的计算机图形学函数,在旋转之前首先要把图形中心平移到(2x,2y),即translate(x,y),现在调用rotate()相当于让图形绕(x,y)旋转(相当于平移之后的原点),然后调用translate(-x,-y),将图形平移回原始位置(x,y)。
function shape(x, y, R,angle,direction)
//x,y是圆心坐标,R是半径,angle调整初始缺口朝向,direction决定旋转方向
{
push();
translate(x,y);
rotate(angle);//将3/4圆形的缺口旋转到合适角度
translate(-x,-y);
translate(x,y);//使3/4圆绕图形中心旋转
if(millis() / 800>=HALF_PI*(num+1))
num++;
rotate(direction*cnt);
translate(-x,-y);
noStroke();
arc(x,y,R,R,0,PI*(3/2),PIE);
pop();
}
以上为绘制每个3/4圆的代码。
关于缺口朝向和旋转方向,根据分析过的特点2和3,利用奇数和偶数的区别来决定。首先假设初始朝向第四象限的位置,即上图所示方向。
缺口朝向:奇数行奇数列,第四象限,
奇数行偶数列,第三象限,即顺时针旋转90°
偶数行偶数列,第二象限,即逆时针旋转180°
偶数行奇数列,第一象限,即顺时针旋转90°
旋转方向:相邻两个相反,又因为每行每列都是偶数个3/4圆,所以实际上只需要一个初始值为-1的参数循环与-1相乘即可。
最后关于旋转的速度,可以看出来它是以正弦曲线的绝对值的斜率大于0那一部分的速度来旋转的,即y=|sinx|的[180k,90+180k],k=0,1,2……的部分。当旋转速度为0的时候,就直接跳过半个周期,进入下一个周期的函数曲线上升部分,否则会出现图形回转的情形,下图中绿色部分为实际用到的部分:
(2)第二张图片基于P5.js的3D图形,即WebGL,图形特点如下:
1.图元为一个小球,以正弦曲线y=sinx的规律沿着z轴运动,同时也向着x轴正方向和y轴负方向做短距离的移动;
2.整体上像是一个球从图像中间凸起来然后凹下去,实际上可以以中心位置的小球为基础,按照据这个小球的远近,以正弦规律规定其余小球的初相位。
function shape(x,y,phase)
{//x,y为小球的位置,phase为初相
push();
translate(x,y,0);
translate(-20,20,120*sin(phase+millis()/500));
noStroke();
ambientMaterial(255,255,255);
sphere(5);
pop();
}
放置小球和规定小球初相的代码如下:
var num=20;
var l=20;
for (var i = num - 1; i >= 0; i--) {
for (var j = num - 1; j >= 0; j--) {
var t=sin(HALF_PI*(num/2-i)/10)+sin(HALF_PI*(num/2-j)/10);
shape(i*l,j*l,t);
shape(-i*l,j*l,t);
shape(i*l,-j*l,t);
shape(-i*l,-j*l,t);
}
}
两层循环中的四个shape()分别在x,y平面的四个象限上摆放小球,参数t是根据小球距离画布中心的距离来确定初相,两个sin函数中都用到了num/2-i或者num/2-j是为了保证在同一个时间,有的小球初相为正,有的小球初相为负,是为了保证突出的球半径足够小,使得运行时能够看出一个球形突出。
三、拓展
(1)去除了在绕自身中心旋转前后的平移操作后,图像的平移会呈现一种破碎重组的规律:
(2)增大了参数t中sin的自变量的值之后(t=sin(HALF_PI*(num/2-i)/5)+sin(HALF_PI*(num/2-j)/5)),突出的一个球成功变成了四个球,加上减少自然光,立体效果更加突出:
(3)添加随机颜色之后的效果更加显著: