JavaScript動畫例項:旋轉的正三角形
給定一個正三角形的重心座標為(x0,y0),高為h,可以用如下的語句繪製一個底邊水平的正三角形。
ctx.beginPath();
ctx.moveTo(x0,y0-h*2/3);
ctx.lineTo(x0+h/Math.sqrt(3), y0+h/3);
ctx.lineTo(x0-h/Math.sqrt(3), y0+h/3);
ctx.lineTo(x0,y0-h*2/3);
ctx.closePath();
ctx.stroke();
給定正三角形個數count,通過迴圈的方式可以繪製出count個重心相同、高度不同正三角形。編寫如下的HTML程式碼。
<!DOCTYPE html>
<html>
<head>
<title>重心相同高度不同的正三角形</title>
</head>
<body>
<canvas id="myCanvas" width="500" height="500" style="border:3px double #996633;">
</canvas>
<script type="text/javascript">
var canvas=document.getElementById('myCanvas');
ctx= canvas.getContext('2d');
var height=360;
var x0=250;
var y0=(500-height)/2-(height/7)+(height*2/3);
var count=4;
ctx.lineWidth=1;
ctx.fillStyle="#FF3388";
ctx.strokeStyle="#FFFFFF";
for (var i=0;i<count;i++)
{
var nHeight = height-(height/count)*i;
ctx.beginPath();
ctx.moveTo(x0,y0-nHeight*2/3);
ctx.lineTo(x0+nHeight/Math.sqrt(3), y0+nHeight/3);
ctx.lineTo(x0-nHeight/Math.sqrt(3), y0+nHeight/3);
ctx.lineTo(x0,y0-nHeight*2/3);
ctx.closePath();
ctx.stroke();
ctx.fill();
};
</script>
</body>
</html>
在瀏覽器中開啟包含這段HTML程式碼的html檔案,可以看到在瀏覽器視窗中繪製出如圖1所示的4個重心相同高度不同的正三角形。
圖1 4個重心相同高度不同的正三角形
若將圖1中除最外層的三角形固定不動外,其餘的3個正三角形繞重心進行旋轉,會產生怎樣的效果呢?
編寫如下的HTML程式碼。
<!DOCTYPE html>
<html>
<head>
<title>旋轉的正三角形</title>
</head>
<body>
<canvas id="myCanvas" width="500" height="500" style="border:3px double #996633;">
</canvas>
<script type="text/javascript">
var canvas=document.getElementById('myCanvas');
ctx= canvas.getContext('2d');
var height=360;
var x0=250;
var y0=(500-height)/2-(height/7)+(height*2/3);
var count=4;
var speed=2;
ctx.lineWidth=1;
ctx.fillStyle="#FF3388";
ctx.strokeStyle="#FFFFFF";
var j = 0;
function draw()
{
ctx.clearRect(0,0,500,500);
ctx.save();
for (var i=0;i<=count;i++)
{
var nHeight = height-(height/count)*i;
ctx.translate(x0,y0);
ctx.rotate(i*j/(80*speed));
ctx.translate(-x0,-y0);
ctx.beginPath();
ctx.moveTo(x0,y0-nHeight*2/3);
ctx.lineTo(x0+nHeight/Math.sqrt(3), y0+nHeight/3);
ctx.lineTo(x0-nHeight/Math.sqrt(3), y0+nHeight/3);
ctx.lineTo(x0,y0-nHeight*2/3);
ctx.closePath();
ctx.stroke();
ctx.fill();
};
ctx.restore();
j++;
if (j>100000) j=0;
}
function move()
{
draw();
requestAnimationFrame(move);
}
move();
</script>
</body>
</html>
在瀏覽器中開啟包含這段HTML程式碼的html檔案,可以看到在瀏覽器視窗中呈現出如圖2所示重心相同高度不同的正三角形繞重心旋轉的動畫效果。
圖2 正三角形繞重心旋轉效果(一)
若將上面程式中語句“var speed=2;”改寫為“var speed=-2;”,其餘部分保持不變,則正三角形會逆時針旋轉,如圖3所示。
圖3 正三角形繞重心旋轉效果(二)
若將增加旋轉的三角形的個數並適當調低旋轉速度的級別,即修改語句:
“var count=4; var speed=2;” 為 “var count=20; var speed=12;”,其餘部分保持不變,則在畫布中呈現出如圖4所示的正三角形旋轉效果。
圖4 正三角形繞重心旋轉效果(三)
由圖2、3或4可以看出,正三角形繞重心旋轉時,越小的三角形旋轉得越快。若將所有的正三角形都用同一種角速度進行旋轉,即簡單地修改語句 “ctx.rotate(i*j/(80*speed));”為“ctx.rotate(j/(80*speed));”,則在畫布中呈現出如圖5所示的正三角形旋轉效果。
圖5 正三角形繞重心旋轉效果(四)
若為旋轉的正三角形設定裁切區域,使得旋轉超出最外層三角形的部分均不可見。編寫如下的HTML檔案。
<!DOCTYPE html>
<html>
<head>
<title>旋轉的正三角形</title>
</head>
<body>
<canvas id="myCanvas" width="500" height="500" style="border:3px double #996633;">
</canvas>
<script type="text/javascript">
var canvas=document.getElementById('myCanvas');
ctx= canvas.getContext('2d');
var height=360;
var x0=250;
var y0=(500-height)/2-(height/7)+(height*2/3);
var count=24;
var speed=18;
ctx.lineWidth=2;
ctx.fillStyle="#FF3388";
ctx.strokeStyle="#FFFFFF";
var j = 0;
function draw()
{
ctx.clearRect(0,0,500,500);
ctx.save();
for (var i=0;i<=count;i++)
{
var nHeight = height-(height/count)*i;
ctx.beginPath();
ctx.moveTo(x0,y0-nHeight*2/3);
ctx.lineTo(x0+nHeight/Math.sqrt(3), y0+nHeight/3);
ctx.lineTo(x0-nHeight/Math.sqrt(3), y0+nHeight/3);
ctx.lineTo(x0,y0-nHeight*2/3);
ctx.closePath();
ctx.clip();
ctx.translate(x0,y0);
ctx.rotate(i*j/(80*speed));
ctx.translate(-x0,-y0);
ctx.beginPath();
ctx.moveTo(x0,y0-nHeight*2/3);
ctx.lineTo(x0+nHeight/Math.sqrt(3), y0+nHeight/3);
ctx.lineTo(x0-nHeight/Math.sqrt(3), y0+nHeight/3);
ctx.lineTo(x0,y0-nHeight*2/3);
ctx.closePath();
ctx.stroke();
ctx.fill();
};
ctx.restore();
j++;
if (j>1000) j=0;
}
function move()
{
draw();
requestAnimationFrame(move);
}
move();
</script>
</body>
</html>
在瀏覽器中開啟包含這段HTML程式碼的html檔案,可以看到在瀏覽器視窗中呈現出如圖6所示旋轉效果。
圖6 正三角形內的旋轉