用p5.js编写简单的动态图形——波纹扩散
第一次使用p5.js写程序,如有错误请指出,多多指教。
没有下载p5.js的小伙伴可以直接使用网页版的,简单注册一个账号之后就可以保存代码啦。
网站:https://editor.p5js.org/
首先看一下要制作的动态图形,如下:
这个图像看上去很简单,如果以灰/黑色为背景,那么这幅图就是一个个半径不同的黑/灰色同心圆在不断收缩自身的“边”,并且收缩的时间不同,造成了波纹晕开的视觉错觉。
那么第一步我要画出这个有“边”的圆,然而,我不知道是我没有找到可以画出圆的边界粗细的函数,还是本身就没有这种函数_(:з)∠)_,所以我采用的方法是,轮流画实心的黑色圆和灰色圆,一层层叠加,也可以构成上图的效果。**要注意到动图中心是黑圆,而先画的圆会被后画的圆遮盖,所以我们要先画黑色圆,再画灰色圆。**代码如下:
var r=16;
function setup()
{
createCanvas(400, 400);
}
function draw() {
background(220);
for(var i=35;i>0;i--)
{
if(i%2==0)
{
fill(220);
ellipse(200,200,r*i);
}
else
{
fill(50);
ellipse(200,200,r*i);
}
}
}
效果如下:
这样同心圆就画完啦。接下来就是要让这个圆动起来,我们注意到,动图中心的黑色圆全程没有动过,所以我选择让灰色的圆动起来。再进行观察,可以发现灰色的圆其实是在进行半径来回放大和缩小的振谐运动,所以我们只要增加自变量参数t(时间)和因变量参数r0(半径变化量),并将两个参数用sin映射,那么我们就可以写出代码:
var r=16;
var t0;
var t1;
var t=0;
var r0;
function setup()
{
createCanvas(400, 400);
}
function draw()
{
background(220);
for(var i=35;i>0;i--)
{
if(i%2==0)
{
fill(220);
t0=sin(t/50);
r0=r*t0;
if(t0>0)
r0=r*t0;
else
r0=0;
ellipse(200,200,r*i+r0);
}
else
{
fill(50);
ellipse(200,200,r*i);
}
}
t++;
}
如下t0=sin(t)图像,当t0>0的时候,r0=r*t0 > 0,这个时候灰色圆的半径是在原来的基础上增加的,当t0=1时,圆的半径达到最大,之后就开始减小直到t0=0的时候图像变回原来的半径,**但是当t0<0时,灰色的圆的半径减小,这个时候图像就会反向变换,灰色圆的半径过小,图片变为全黑。**所以当t0<0时,令r0=0,图像就不会变换。
接着我们发现这个图像上的所有同心圆是一起运动,没有制作出波纹的感觉,所以我们要加上时间差,也就是改变sin函数的相位。假如这个图上有10个圆,每个圆做完一次振谐运动(所用时间设为T),并且停止运动(时间也为T),不断循环,那么我们应该在2T内做完10个圆的运动,才能续上下一个循环,用函数表示,如下图(看图就简单多了):
因此每个同心的sin函数的相位为(pi / 35)*i ,所以我们最终代码应该是:
var r=16;
var t0;
var t1;
var t=0;var r0;
var pi=3.1415926;
function setup()
{
createCanvas(400, 400);
}
function draw()
{
background(220);
for(var i=35;i>0;i--)
{
if(i%2==0)
{
fill(220);
t0=sin((t-(pi/35)*i)*4);
if(t0>0)
r0=r*t0;
else
r0=0;
ellipse(200,200,r*i+r0);
}
else
{
fill(50);
ellipse(200,200,r*i);
}
}
t+=0.01;
}
注:t+=0.01,sin的变量*5,这些改变为了图像变换的速度更美观,不影响变换规律。
最终的效果如下图:
接下来是修改参数后变形的动态图像:
所作的变换是:t0=sin((t-(pi/35)*i)4)——>t0=sin((it+pi/(i+2))*5)
小结
其实是很简单的编程,代码也就30多行,但是一开始我没有发现规律,让我头秃了很久,后来在纸上推演了一下sin函数的变换,一下子就解开了,打草稿真的是好习惯_(:з)∠)_