您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center   Code  
会员   
   
 
     
   
 订阅
  捐助
HTML5 Canvas:制作动画特效
 
  9725  次浏览      21
 2018-2-11 
 
编辑推荐:
本文来自于jquery之家 ,html5制作canvas动画的基本步骤,控制canvas动画和实例代码。

要在 HTML5 canvas 中绘制图像动画效果,你需要绘制出每一帧的图像,然后在一个极短的时间内从一帧过渡到下一帧,形成动画效果。这其实是一种视觉欺骗,原理就像播放电影一样,胶片上每一格是一帧图片,然后快速的播放它们,在人的眼睛看来就是一个完整的动画效果。

制作canvas动画的基本步骤

下面是你在canvas上绘制一个动画帧的基本步骤:

  • 1、清空canvas:除了背景图像之外,你需要清空之前绘制的所有图形。
  • 2、保存canvas的状态:如果在这一步中你使用了不同的绘图状态(例如描边大小和填充色等),并且你想在绘制每一帧时使用相同的原始状态,你需要保存这些原始状态。
  • 3、绘制动画图形:这一步中你需要绘制那些动画的图形元素。
  • 4、恢复canvas状态:如果你之前保存过canvas的状态,在这一步中将它们恢复。

控制canvas动画

我们需要一种方法来在指定时间内执行我们的绘制图形函数。有两种方式可以控制动画的执行。

第一种是使用下面的三个window对象上的方法:window.setInterval(),window.setTimeout()和window.requestAnimationFrame()。它们都能在指定时间内调用指定的函数。

  • setInterval(function, delay):在每delay毫秒时间内反复执行function指定的函数。
  • setTimeout(function, delay):在delay毫秒内执行function指定的函数。
  • requestAnimationFrame(callback):通知浏览器你需要执行一个动画,并请求浏览器调用指定的函数来在下一次重绘前更新动画。

第二种方法是使用事件监听。例如你需要做一个小游戏,你可以监听键盘和鼠标的事件,然后在捕获相应的事件时使用setTimeout()方法来制作动画效果。

为了获得更好的动画性能,我们通常使用requestAnimationFrame()方法。当浏览器装备好绘制下一帧动画时,我们可以将绘制函数作为参数传入这个方法中。

通过在浏览器准备画下一帧的时候,给浏览器发出信号,可以使浏览器对你的动画进行硬件加速,这比使用setTimeout()来绘制动画效果会好得多。

下面是一段示例代码:

function animate() {

reqAnimFrame = window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame
;

reqAnimFrame(animate);

draw();
}

animate()函数首先会获取requestAnimationFrame()函数的一个引用。注意在不同的浏览器中会使用不同的名称。变量reqAnimFrame会在不同的浏览器中设置为不同的值,总之它不能为空。

然后reqAnimFrame()方法被调用,并将animate()函数作为参数传入。当浏览器准备好绘制下一帧动画时,animate()函数就会被调用。

最后,animate()函数会调用draw()方法。draw()方法在上面的代码中没有写出来,它实际上做的事情就是前面提到的绘制一个动画帧的4个步骤:清空canvas,保存状态,绘制图形,恢复状态。

还有一件需要注意的事情是animate()函数必须被调用一次来启动动画,否则requestAnimationFrame()函数将永远不会被调用,动画也不会被正常执行。

下面是一个小例子:一个小矩形在canvas中来回不停的运动。

上面canvas动画的实现代码如下:

var x = 0;
var y = 15;
var speed = 5;
function animate() {
reqAnimFrame = window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame
;
reqAnimFrame(animate);
x += speed;
if(x <= 0 || x >= 475){
speed = -speed;
}
draw();
}
function draw() {
var canvas = document.getElementById("ex1");
var context = canvas.getContext("2d");
context.clearRect(0, 0, 500, 170);
context.fillStyle = "#ff00ff";
context.fillRect(x, y, 25, 25);
}
animate();

canvas动画示例

下面是一个地球绕太阳以及月亮绕地球旋转的canvas动画效果。

上面效果的实现代码如下:

var sun = new Image();
var moon = new Image();
var earth = new Image();
function init(){
sun.src = 'img/Canvas_sun.png';
moon.src = 'img/Canvas_moon.png';
earth.src = 'img/Canvas_earth.png';
reqAnimFrame = window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame
;
reqAnimFrame(drawSolarSystem);
}

function drawSolarSystem () {
var ctx = document.getElementById('ex2').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);

reqAnimFrame = window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame
;
reqAnimFrame(drawSolarSystem);
}

init();

接下来的例子是一个模拟时钟动画的例子。

模拟时钟动画的实现代码如下:

function clock(){
var now = new Date();
var ctx = document.getElementById('ex3').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 = "rgba(0,0,0,0)";
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();

reqAnimFrame = window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame
;
reqAnimFrame(clock);
}

reqAnimFrame = window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame
;
reqAnimFrame(clock);
   
9725 次浏览       21
相关文章

深度解析:清理烂代码
如何编写出拥抱变化的代码
重构-使代码更简洁优美
团队项目开发"编码规范"系列文章
相关文档

重构-改善既有代码的设计
软件重构v2
代码整洁之道
高质量编程规范
相关课程

基于HTML5客户端、Web端的应用开发
HTML 5+CSS 开发
嵌入式C高质量编程
C++高级编程