canvas动画教程-1 引言

参加工作以来做了很多和canvas相关的工作,也因此看了一些相关的书籍和文章,所学很是杂乱,于是便有了这些文章,对以往所学进行梳理,以供将来复习所用。 这个系列的文章不会系统的介绍canvas相关的API,有兴趣可以去看API文档。我们只在引言部分简单介绍一下canvas绘制的基本流程和canvas动画的基本原理。

1. canvas绘制的基本流程

canvas的绘制流程很简单,大致上有一个套路,分为如下几步:

  1. 获取指向canvas的引用
  2. 使用getContext方法获取绘图环境变量
  3. 使用绘图环境变量在canvas元素上进行绘制 先通过一个例子来看如何在canvas上绘制一个Hello Canvas。首先我们需要在HTML里插入一个canvas标签:
<canvas id="canvas" width="600" height="300">
    Canvas not support!
</canvas>
复制代码

标签里面的面的内容“Canvas not support!”只有在浏览器不支持canvas的时候才会显示出来。
接下来看js代码:

//1. 获取指向canvas的引用
var canvas = document.getElementById("canvas");
//2. 获取指向canvas的引用
var context = canvas.getContext('2d');

//3.使用绘图环境变量在canvas元素上进行绘制
context.font = "38pt Arial";
context.fillStyle = "cornflowerblue";
context.strokeStyle = "blue";

context.fillText("Hello Canvas", canvas.width / 2 - 150, canvas.height / 2 + 15);
context.strokeText("Hello Canvas", canvas.width / 2 - 150, canvas.height / 2 + 15);
复制代码

这样,就得到了一个很基础的图形:

2. canvas动画的基本原理

在canvas中实现动画的原理很简单,就是在播放动画时持续更新并绘制。最简单的做法,就是在每一帧中擦除上一帧的内容,然后重新绘制这一帧的内容。那么如何实现这种持续的更新呢?
首先可以想到用while循环:

function animate(){
  //这里面写动画更新逻辑
}

while(true){
  animate();  
}
复制代码

但是while循环是一个死循环,会导致浏览器失去响应,而且也无法绘制出动画的效果,因此应该排除。
然后我们可以想到用一些异步的方法,如setTimeout或者setInterval:

/**
* 使用setInterval
**/
function animate(){
  //这里面写动画更新逻辑
}

setInterval(animate, 1000/60);

/**
* 使用setTimeout
**/
function animate(){
  var start = +new Date(),
      finish;
      
  //这里面写动画更新逻辑
  
  finish = +new Date();
  setTimeout(animate, (1000/60) - (finish-start));
}
复制代码

使用setTimeout和setInterval确实可以实现持续的更新,但是这两个方法并不是专门为动画而设计的,他们有如下缺陷:

  1. 都是通用方法,并不是专门为动画设计
  2. 即使向其传递以毫秒为单位的参数值,也达不到毫秒的精确度
  3. 没有对调用动画循环的机制作优化
  4. 不会考虑动画的最佳时机,只会以某个大致的时间间隔来调用动画循环 基于以上原因,使用这两个方法来绘制canvas动画,其效果可能不如预期流畅,而且还会占用其他资源。
    因此,浏览器提供了一个名为requestAnimationFrame()的方法。从这个方法的名字就可以感觉到,它是专门为动画而生的。因为浏览器是知道绘制的最佳时机的,它会在可以绘制时通知你,而requestAnimationFrame正是用来实现此功能的。该方法不需要使用者指定帧速率,浏览器会自行决定最佳帧速率。
    现在,我们就用这个方法来实现一个简单的动画。向HTML里插入一个id为canvas2的canvas标签,js代码如下:
var canvas2 = document.getElementById("canvas2"),
    ctx = canvas2.getContext('2d'),
    img = new Image(),
    x = 0,
    y = 0;

img.onload = function () {
    animate();
}

img.src = './images/ball.png';

function animate() {
    //擦除上一帧的内容
    ctx.clearRect(0, 0, canvas2.width, canvas2.height);

    //更新逻辑
    x += 2;
    y++;
    ctx.drawImage(img, x, y, img.width, img.height);

    //持续更新
    requestAnimationFrame(animate);
}
复制代码

这样就实现了一个动画效果:


requestAnimationFrame的缺点,主要是兼容性问题。后续章节中我们会提供一个polyfill方法实现一个兼容性比较好的解决方案。

小结

本文主要介绍了canvas的基本用法和动画原理。为了使用方便,后续章节不会再用这些基本的API,而是对它们进行了一些封装,实现了几个基本的类,如Stage、Renderer、Sprite、Graphics和Loader等,在下一篇文章中会有一个简单的介绍。
最后为大家推荐几本学习canvas的书籍,这个系列文章的大部分知识点都是来源于这几本书。

  • HTML5 Canvas核心技术-图形、动画与游戏开发。这本书系统而又详细地介绍了canvas相关的API及用法,以及各种物理效果、碰撞检测等技术,最后实现了一个简单的游戏引擎,在此基础上开发了一个弹珠游戏,并用canvas实现了一些自定义控件。该书内容丰富,十分推荐。

奉上本系列文章所涉及的源码的git地址,喜欢的话麻烦给个star哦!

相关文章列表

转载于:https://juejin.im/post/5bb9f9005188255c7566e21d

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值