基本动画的步骤 Basic animation steps
用canvas画一帧动画,通常需要以下四个步骤:
1. 清空 canvas
除非接下来要画的内容会完全充满 canvas (例如背景图),否则你需要清空所有。最简单的做法就是用 clearRect 方法。
2. 保存 canvas 状态
如果你要改变一些会改变 canvas 状态的设置(样式,变形之类的),又要在每画一帧之时都是原始状态的话,你需要先保存一下。
3. 绘制动画图形(animated shapes)
这一步才是重绘动画帧。
4. 恢复 canvas 状态
如果已经保存了 canvas 的状态,可以先恢复它,然后重绘下一帧。
在操作动画过程中,我们需要一些可以定时执行重绘的方法。有两种方法可以实现这样的动画操控:
第一种方法:可以通过 setInterval 和 setTimeout 方法来控制在设定的时间点上执行重绘。
第二种方法:我们可以利用用户输入来实现操控。如果需要做一个游戏,我们可以通过监听用户交互过程中触发的事件(如 keyboard,mouse)来控制动画效果。
下面是用第一种方法实现的一个时钟动画:
<script type="text/javascript"> function clock(){ var ctx = document.getElementById("canvas").getContext("2d"); ctx.save(); ctx.clearRect(0, 0, 150, 150); ctx.translate(75, 75); ctx.scale(0.5, 0.5); ctx.rotate(-Math.PI/2); /*******************************************************/ //1.画表盘 /*******************************************************/ ctx.beginPath(); ctx.lineWidth = 30; var lgd = ctx.createLinearGradient(0, 0, 50, 75); lgd.addColorStop(0, "#E0E3EC"); lgd.addColorStop(1, "#9AA0A0"); ctx.strokeStyle = lgd; var rgd = ctx.createRadialGradient(0, 0, 0, 0, 0, 150); rgd.addColorStop(0, "#FFF"); rgd.addColorStop(1, "#325FA2"); ctx.fillStyle = rgd; ctx.arc(0, 0, 135, 0, Math.PI*2, true); ctx.stroke(); ctx.fill(); //全局设置,以后的线条都使用该设置 ctx.strokeStyle = "#FFFEF5"; ctx.lineCap = "square"; //画12个时刻刻度 ctx.save(); //保存状态 ctx.lineWidth = 8; //设置线条粗细 ctx.beginPath(); for(var i = 0; i < 12; i++){ //以当前原点为圆心旋转30度 ctx.rotate(Math.PI/6); //以圆心外100像素处为起点,120像素处为终点画线 ctx.moveTo(100, 0); ctx.lineTo(120, 0); ctx.stroke(); } //恢复状态,将取出的状态作为当前状态 ctx.restore(); /*******************************************************/ //2.画60个分钟刻度 /*******************************************************/ ctx.save(); ctx.lineWidth = 5; for(i = 0; i < 60; i++){ if(i%5 != 0){ ctx.beginPath(); ctx.moveTo(117, 0); ctx.lineTo(120, 0); ctx.stroke(); } //旋转6度 ctx.rotate(Math.PI/30); } ctx.restore(); var now = new Date(); var sec = now.getSeconds(); var min = now.getMinutes(); var hr = now.getHours(); hr = hr > 12? hr-12:hr; /*******************************************************/ //3.画时针 /*******************************************************/ ctx.save(); //指针转向当前位置 ctx.rotate(hr*(Math.PI/6) + min*(Math.PI/360) + sec*(Math.PI/21600)); //设置时针宽度 ctx.lineWidth = 10; ctx.beginPath(); ctx.moveTo(-20, 0); ctx.lineTo(70, 0); ctx.stroke(); ctx.restore(); /*******************************************************/ //4.画分针 /*******************************************************/ ctx.save(); ctx.rotate(min*(Math.PI/30) + sec*(Math.PI/1800)); ctx.lineWidth = 8; ctx.beginPath(); ctx.moveTo(-28, 0); ctx.lineTo(90, 0); ctx.stroke(); ctx.restore(); /*******************************************************/ //5.画秒针 /*******************************************************/ ctx.save(); ctx.rotate(sec*(Math.PI/30)); ctx.lineWidth = 6; ctx.beginPath(); ctx.moveTo(-30, 0); ctx.lineTo(120, 0); ctx.stroke(); ctx.restore(); /*******************************************************/ //6.画中心点 /*******************************************************/ ctx.beginPath(); ctx.fillStyle = rgd; ctx.arc(0, 0, 10, 0, Math.PI*2); ctx.fill(); ctx.restore(); } function initClock(){ clock(); setInterval(clock, 1000); } </script>
<body onLoad="initClock()"> <canvas id="canvas" width="150" height="150" >It's a clock here </canvas> </body>
效果图如下: