今天看到一篇CSS3寫的大風車http://www.cnblogs.com/yaojaa/archive/2013/01/30/2882521.html,感覺CSS3太神奇了,這在以前用CSS是想都不敢想的。記得去年自己用canvas也寫過這樣的大風車,今天我打算用canvas制作一個一模一樣的,連速度都一致的大風車。
大家請看下面兩張圖,你們看得出這兩張圖有什么區別嗎?哪張是CSS3寫的哪張是canvas寫的?
下面就來介紹制作風車的過程。先上代碼吧:

<!DOCTYPE html> <html> <head> <title></title> </head> <body> <canvas id = "canvas" width="300" height="300"></canvas> <script> (function () { var Pinwheel = function (canvas, options) { this.canvas = document.getElementById(canvas); this.options = options; }; Pinwheel.prototype = { constructor: Pinwheel, show: function () { var canvas = this.canvas,//取得canvas元素 width = canvas.width,//canvas元素的寬度 height = canvas.height,//canvas元素的高度 color = this.options.color,//風車葉子的顏色 radius = this.options.radius,//整個風車的半徑 wheelRadius = this.options.wheelRadius,//風車葉子的半徑 part = this.options.part,//PI/2分成幾份 ctx = canvas.getContext("2d"),//獲取上下文 num = this.options.num,//葉子數量 center = {x: width / 2, y: height / 2},//繪圖區域的中心 point, //葉子圓心位置 start = 0,//繪制葉子的開始角 angle = 0,//start = angle end = Math.PI,//繪制葉子的結束角 offset = Math.PI * (360 / num) / 180,//兩個相鄰葉子之間的角度 rotateAngle = offset / part;//每次旋轉的角度 // window.timer = setInterval(function () { ctx.clearRect(0, 0, width, height); for (var i = 0; i < num; i += 1) { ctx.beginPath();//開始繪制葉子 var wheelGradient = ctx.createRadialGradient(center.x, center.y, 100, center.x, center.y, 0);//創建徑向漸變 wheelGradient.addColorStop(0, color[i]);//起始顏色 wheelGradient.addColorStop(1, "#000");//結束顏色 ctx.fillStyle = wheelGradient;//填充漸變樣式 point = {x: center.x + Math.cos(offset * i + angle) * radius, y: center.y + Math.sin(offset * i + angle) * radius};//葉子圓心位置 var x = start + offset * i;//繪制葉子的開始角 var y = end + offset * i;//繪制葉子的結束角 ctx.arc(point.x, point.y, wheelRadius, x, y, false);//繪制 ctx.fill();//填充 ctx.closePath();//結束繪制 } ctx.beginPath(); var dotGradient = ctx.createRadialGradient(center.x, center.y, 0, center.x, center.y, 40); dotGradient.addColorStop(0, "#fff"); dotGradient.addColorStop(1, "#666"); ctx.fillStyle = dotGradient; ctx.arc(center.x, center.y, 25, 0, 2 * Math.PI, false); ctx.fill(); ctx.closePath(); angle += rotateAngle; start = angle; end = Math.PI + angle; // }, 20) }, hide: function () { clearInterval(window.timer); } }; var options = { num: 4, color: ["red", "yellow", "blue", "green"], radius: 50, wheelRadius: 50, part: 50 }; var a = new Pinwheel("canvas", options); a.show(); }()); </script> </body> </html>
首先,確定需要的各項參數:
var canvas = this.canvas,//取得canvas元素 width = canvas.width,//canvas元素的寬度 height = canvas.height,//canvas元素的高度 color = this.options.color,//風車葉子的顏色 radius = this.options.radius,//整個風車的半徑 wheelRadius = this.options.wheelRadius,//風車葉子的半徑 part = this.options.part,//PI/2分成幾份 ctx = canvas.getContext("2d"),//獲取上下文 num = this.options.num,//葉子數量 center = {x: width / 2, y: height / 2},//繪圖區域的中心 point, //葉子圓心位置 start = 0,//繪制葉子的開始角 angle = 0,//start = angle end = Math.PI,//繪制葉子的結束角 offset = Math.PI * (360 / num) / 180,//兩個相鄰葉子之間的角度 rotateAngle = offset / part;//每次旋轉的角度
循環繪制每個葉子:
for (var i = 0; i < num; i += 1) { ctx.beginPath();//開始繪制葉子 var wheelGradient = ctx.createRadialGradient(center.x, center.y, 100, center.x, center.y, 0);//創建徑向漸變 wheelGradient.addColorStop(0, color[i]);//起始顏色 wheelGradient.addColorStop(1, "#000");//結束顏色 ctx.fillStyle = wheelGradient;//填充漸變樣式 point = {x: center.x + Math.cos(offset * i + angle) * radius, y: center.y + Math.sin(offset * i + angle) * radius};//葉子圓心位置 var x = start + offset * i;//繪制葉子的開始角 var y = end + offset * i;//繪制葉子的結束角 ctx.arc(point.x, point.y, wheelRadius, x, y, false);//繪制 ctx.fill();//填充 ctx.closePath();//結束繪制 }
繪制中間的大圓點:
ctx.beginPath(); var dotGradient = ctx.createRadialGradient(center.x, center.y, 0, center.x, center.y, 40); dotGradient.addColorStop(0, "#fff"); dotGradient.addColorStop(1, "#666"); ctx.fillStyle = dotGradient; ctx.arc(center.x, center.y, 25, 0, 2 * Math.PI, false); ctx.fill(); ctx.closePath();
上面的代碼已經可以制作靜態的風車了,但是我們要做的是動態的,於是我們需要一個計時器。下面是計時器代碼:
window.timer = setInterval(function () { ctx.clearRect(0, 0, width, height);//每次調用計時器需要重繪 for (var i = 0; i < num; i += 1) { ctx.beginPath();//開始繪制葉子 var wheelGradient = ctx.createRadialGradient(center.x, center.y, 100, center.x, center.y, 0);//創建徑向漸變 wheelGradient.addColorStop(0, color[i]);//起始顏色 wheelGradient.addColorStop(1, "#000");//結束顏色 ctx.fillStyle = wheelGradient;//填充漸變樣式 point = {x: center.x + Math.cos(offset * i + angle) * radius, y: center.y + Math.sin(offset * i + angle) * radius};//葉子圓心位置 var x = start + offset * i;//繪制葉子的開始角 var y = end + offset * i;//繪制葉子的結束角 ctx.arc(point.x, point.y, wheelRadius, x, y, false);//繪制 ctx.fill();//填充 ctx.closePath();//結束繪制 } ctx.beginPath(); var dotGradient = ctx.createRadialGradient(center.x, center.y, 0, center.x, center.y, 40); dotGradient.addColorStop(0, "#fff"); dotGradient.addColorStop(1, "#666"); ctx.fillStyle = dotGradient; ctx.arc(center.x, center.y, 25, 0, 2 * Math.PI, false); ctx.fill(); ctx.closePath(); angle += rotateAngle; start = angle; end = Math.PI + angle;
}, 20)
動態的風車基本上就做完了,這是運行大風車代碼:
var options = { num: 4, color: ["red", "yellow", "blue", "green"], radius: 50, wheelRadius: 50, part: 50 }; var a = new Pinwheel("canvas", options); a.show();
修改options對象的屬性就會改變風車的狀態。
需要停止風車運轉調用這個函數:
hide: function () { clearInterval(window.timer); }
下面是展示結果的時候了:
以前寫這些代碼是沒有注釋的,今天花了好大功夫加上注釋,然后在原有基礎上做了一些修改,做成了和CSS3寫的一模一樣的風車。