​像素流Peer Stream​

Canvas特效之魔鬼四边形_算法

如图所示

  • 动画在一个圆形区域内的二维动画。

  • 若干个同心四边形(矩形框、方框)以正弦函数的规律来回旋转。

  • 边长更大的四边形质量更大,“惯性”也看上去更大,整体看来,像是中心的旋转力量带动了周围四边形的旋转。

  • 四边形的颜色是任意的不透明的饱和色,亮度适中。


首先需要一个<canvas>画板,并指定任意的宽高:

<canvas id="canvas" width="500" height="500"></canvas>

接下来通过getContext函数定义它为二维画板,接着将canvas的宽和高中最小的一边作为圆形区域的直径,通过CanvasRenderingContext2D的clip方法限定圆形绘画区域,完整的代码如下:

const $ = canvas.getContext("2d");
const l = Math.min(canvas.width, canvas.height) / 2;


$.strokeStyle = `hsl(${360 * Math.random()}deg 100% 50%)`;
$.lineWidth = 6;


$.beginPath();
$.arc(l, l, l, 0, Math.PI * 2);
$.clip();


(function frame(time) {
$.clearRect(-l, -l, l * 2, l * 2);


for (let x = 1; x <= l; x += $.lineWidth + 2) {
$.strokeRect(-x, -x, x * 2, x * 2);
const theta = Math.sin(x / l - time / 512) * 60;
$.setTransform(new DOMMatrix().translate(l, l).rotate(0, 0, theta));
}


window.animationFrame = requestAnimationFrame(frame);
})(0);

然后我们使用CSS的hsl函数生成随机的饱和亮色,使得特效更鲜艳。在256 x 256 x 256 = 16777216种真彩色中,只有256 x 256 x 3 = 196608种饱和色,约占总数的1%,剩下的颜色都是不鲜艳的,而这1%的饱和色中又只有256 x 6 = 1536种亮色,剩下的都不够亮。所以既饱和又明亮的颜色只占总数的(256 x 6) / (256 x 256 x 256) ≈ 0.009%,在色谱上,只有一条边属于这个范围:

Canvas特效之魔鬼四边形_python_02

接下来我们要定义每一帧的函数frame(time),然后通过requestAnimationFrame来循环调用frame,并且传入当前的时刻time,我们利用这个时刻来计算当时每个四边形的旋转角度。每一帧中,先使用clearRect函数清除掉上一帧的画面,然后遍历每个四边形,矩形边框(四边形)之间保持一定的间隙,最后在正弦函数中决定这个方框的角度,角度和当前时刻和方框的边长都有关系,所以Math.sin中传入了2个变量:空间变量x(边长)和时间变量time(时刻)。最终调用strokeRect函数画出方框,就实现了魔鬼四边形特效:

Canvas特效之魔鬼四边形_python_03