视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
canvas游戏开发学习之八:基本动画
2020-11-27 15:13:23 责编:小采
文档
 由于我们是用脚本去操控 canvas 对象,这样要实现一些交互动画也是相当容易的。只不过,canvas 从来都不是专门为动画而设计的(不像 Flash),难免会有些。可能最大的就是图像一旦绘制出来,它就是一直保持那样了。如果需要移动它,我们不得不对所有东西(包括之前的)进行重绘。重绘是相当费时的,而且性能很依赖于电脑的速度。

基本动画的步骤 Basic animation steps

画一帧,你需要以下一些步骤:

清空 canvas除非接下来要画的内容会完全充满 canvas (例如背景图),否则你需要清空所有。最简单的做法就是用clearRect方法。如果你要改变一些会改变 canvas 状态的设置(样式,变形之类的),又要在每画一帧之时都是原始状态的话,你需要先保存一下。

绘制动画图形(animated shapes)
这一步才是重绘动画帧。
恢复 canvas 状态如果已经保存了 canvas 的状态,可以先恢复它,然后重绘下一帧。

操控动画 Controlling an animation在 canvas 上绘制内容是用 canvas 提供的或者自定义的方法,而通常,我们仅仅在脚本执行结束后才能看见结果,比如说,在 for 循环里面做完成动画是不太可能的。我们需要一些可定时的执行重绘的方法。有两种方法可以实现这样的动画操控。首先可以通过setInterval和setTimeout方法来控制在设定的时间点上执行重绘。

setInterval(animateShape,500); 
 setTimeout(animateShape,500);

动画例子 1

这个例子里面,我会让一个小型的太阳系模拟系统动起来。

var sun = new Image(); 
 var moon = new Image(); 
 var earth = new Image(); 
 function init(){ 
 sun.src = 'images/sun.png'; 
 moon.src = 'images/moon.png'; 
 earth.src = 'images/earth.png'; 
 setInterval(draw,100); 
 } 
 
 function draw() { 
 var ctx = document.getElementById('canvas').getContext('2d'); 
 
 ctx.globalCompositeOperation = 'destination-over'; 
 ctx.clearRect(0,0,300,300); // clear canvas 
 
 ctx.fillStyle = 'rgba(0,0,0,0.4)'; 
 ctx.strokeStyle = 'rgba(0,153,255,0.4)'; 
 ctx.save(); 
 ctx.translate(150,150); 
 
 // Earth 
 var time = new Date(); 
 ctx.rotate( ((2*Math.PI)/60)*time.getSeconds() + ((2*Math.PI)/60000)*time.getMilliseconds() ); 
 ctx.translate(105,0); 
 ctx.fillRect(0,-12,50,24); // Shadow 
 ctx.drawImage(earth,-12,-12); 
 
 // Moon 
 ctx.save(); 
 ctx.rotate( ((2*Math.PI)/6)*time.getSeconds() + ((2*Math.PI)/6000)*time.getMilliseconds() ); 
 ctx.translate(0,28.5); 
 ctx.drawImage(moon,-3.5,-3.5); 
 ctx.restore(); 
 
 ctx.restore(); 
 
 ctx.beginPath(); 
 ctx.arc(150,150,105,0,Math.PI*2,false); // Earth orbit 
 ctx.stroke(); 
 
 ctx.drawImage(sun,0,0,300,300); 
}

动画例子 2

function init(){ 
 clock(); 
 setInterval(clock,1000); 
 } 
 function clock(){ 
 var now = new Date(); 
 var ctx = document.getElementById('canvas').getContext('2d'); 
 ctx.save(); 
 ctx.clearRect(0,0,150,150); 
 ctx.translate(75,75); 
 ctx.scale(0.4,0.4); 
 ctx.rotate(-Math.PI/2); 
 ctx.strokeStyle = "black"; 
 ctx.fillStyle = "white"; 
 ctx.lineWidth = 8; 
 ctx.lineCap = "round"; 
 
 // Hour marks 
 ctx.save(); 
 for (var i=0;i<12;i++){ 
 ctx.beginPath(); 
 ctx.rotate(Math.PI/6); 
 ctx.moveTo(100,0); 
 ctx.lineTo(120,0); 
 ctx.stroke(); 
 } 
 ctx.restore(); 
 
 // Minute marks 
 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(); 
 } 
 ctx.rotate(Math.PI/30); 
 } 
 ctx.restore(); 
 
 var sec = now.getSeconds(); 
 var min = now.getMinutes(); 
 var hr = now.getHours(); 
 hr = hr>=12 ? hr-12 : hr; 
 
 ctx.fillStyle = "black"; 
 
 // write Hours 
 ctx.save(); 
 ctx.rotate( hr*(Math.PI/6) + (Math.PI/360)*min + (Math.PI/21600)*sec ) 
 ctx.lineWidth = 14; 
 ctx.beginPath(); 
 ctx.moveTo(-20,0); 
 ctx.lineTo(80,0); 
 ctx.stroke(); 
 ctx.restore(); 
 
 // write Minutes 
 ctx.save(); 
 ctx.rotate( (Math.PI/30)*min + (Math.PI/1800)*sec ) 
 ctx.lineWidth = 10; 
 ctx.beginPath(); 
 ctx.moveTo(-28,0); 
 ctx.lineTo(112,0); 
 ctx.stroke(); 
 ctx.restore(); 
 
 // Write seconds 
 ctx.save(); 
 ctx.rotate(sec * Math.PI/30); 
 ctx.strokeStyle = "#D40000"; 
 ctx.fillStyle = "#D40000"; 
 ctx.lineWidth = 6; 
 ctx.beginPath(); 
 ctx.moveTo(-30,0); 
 ctx.lineTo(83,0); 
 ctx.stroke(); 
 ctx.beginPath(); 
 ctx.arc(0,0,10,0,Math.PI*2,true); 
 ctx.fill(); 
 ctx.beginPath(); 
 ctx.arc(95,0,10,0,Math.PI*2,true); 
 ctx.stroke(); 
 ctx.fillStyle = "#555"; 
 ctx.arc(0,0,3,0,Math.PI*2,true); 
 ctx.fill(); 
 ctx.restore(); 
 
 ctx.beginPath(); 
 ctx.lineWidth = 14; 
 ctx.strokeStyle = '#325FA2'; 
 ctx.arc(0,0,142,0,Math.PI*2,true); 
 ctx.stroke(); 
 
 ctx.restore(); 
 }

下载本文
显示全文
专题