一、概述
canvas 的英文意思是帆布,是 h5 的一个新的 html 元素,从意思上来讲,你可以在这块帆布上绘制一些图案,甚至是动画和 3D。
<canvas id="tutorial" width="150" height="150"></canvas>
二、基本用法
渲染上下文(The rendering context)
canvas 是一个画布,它暴露一个或多个渲染上下文,用来绘制内容。这相当于多个画笔;
var canvas = document.getElementById('tutorial');
var ctx = canvas.getContext('2d');
栅格:

左上角为画笔(渲染上下文)的笔触,可以使用 ctx.moveTo(x,y) 移动到任意位置。
三、基本功能
1.绘制形状
api
- fillRect(x, y, width, height) 绘制一个填充的矩形
- strokeRect(x, y, width, height) 绘制一个矩形的边框
- clearRect(x, y, width, height) 清除指定矩形区域,让清除部分完全透明
- lineTo(x, y) 绘制一条从当前位置到指定 x 以及 y 位置的直线
- arc(x, y, radius, startAngle, endAngle, anticlockwise) 画一个以(x,y)为圆心的以 radius 为半径的圆弧(圆)
思路
- 首先,你需要创建路径起始点;
- 然后你使用画图命令去画出路径;
- 之后你把路径封闭。
- 一旦路径生成,你就能通过描边或填充路径区域来渲染图形。
// 输出一个笑脸
function draw() {
var canvas = document.getElementById('canvas');
if (canvas.getContext){
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.arc(75,75,50,0,Math.PI*2,true); // 绘制
ctx.moveTo(110,75);
ctx.arc(75,75,35,0,Math.PI,false); // 口(顺时针)
ctx.moveTo(65,65);
ctx.arc(60,65,5,0,Math.PI*2,true); // 左眼
ctx.moveTo(95,65);
ctx.arc(90,65,5,0,Math.PI*2,true); // 右眼
ctx.stroke();
}
}
记录绘画命令
- Path2D() 会返回一个新初始化的 Path2D 对象,用来缓存或记录绘画命令,这样你将能快速地回顾路径。
- Path2D.addPath(path [, transform]) 添加了一条路径到当前路径(可能添加了一个变换矩阵)
2.填充样式和颜色
- fillStyle = color 设置图形的填充颜色
- strokeStyle = color 设置图形轮廓的颜色
3.绘制文本
- fillText(text, x, y [, maxWidth]) 在指定的(x,y)位置填充指定的文本
- strokeText(text, x, y [, maxWidth]) 在指定的(x,y)位置绘制文本边框
4.使用图片
基本操作
- 获得一个指向 HTMLImageElement 的对象或者另一个 canvas 元素的引用作为源,也可以通过提供一个 URL 的方式来使用图片;
- 使用 drawImage()函数将图片绘制到画布上;
var img = new Image(); // 创建img元素
img.onload = function(){
// 执行drawImage语句
ctx.drawImage(img,0,0);
ctx.beginPath();
ctx.moveTo(30,96);
ctx.lineTo(70,66);
ctx.lineTo(103,76);
ctx.lineTo(170,15);
ctx.stroke();
}
img.src = 'myImage.png'; // 设置图片源地址
API
- drawImage(image, x, y)
- image 是 image 或者 canvas 对象
- x 和 y 是其在目标 canvas 里的起始坐标
5.动画制作
基本步骤
- 清空 canvas
- 除非接下来要画的内容会完全充满 canvas (例如背景图),否则你需要清空所有;
- 最简单的做法就是用 clearRect 方法;
- 保存 canvas 状态
- 如果你要改变一些会改变 canvas 状态的设置(样式,变形之类的),又要在每画一帧之时都是原始状态的话,你需要先保存一下;
- 绘制动画图形(animated shapes)
- 这一步才是重绘动画帧;
- 恢复 canvas 状态
- 如果已经保存了 canvas 的状态,可以先恢复它,然后重绘下一帧;
操控动画
- 首先,可以用 window.setInterval(), window.setTimeout(),和 window.requestAnimationFrame()来设定定期执行一个指定函数。 - requestAnimationFrame(callback) 告诉浏览器你希望执行一个动画,并在重绘之前,请求浏览器执行一个特定的函数来更新动画; - 如果你并不需要与用户互动,你可以使用 setInterval()方法,它就可以定期执行指定代码; - 如果我们需要做一个游戏,我们可以使用键盘或者鼠标事件配合上 setTimeout()方法来实现;
//下面的例子,采用 window.requestAnimationFrame()实现动画效果。
//这个方法提供了更加平缓并更加有效率的方式来执行动画,当系统准备好了重绘条件的时候,才调用绘制动画帧。
//一般每秒钟回调函数执行60次,也有可能会被降低。
// 模拟太阳系动画
var sun = new Image();
var moon = new Image();
var earth = new Image();
function init(){
sun.src = 'https://mdn.mozillademos.org/files/1456/Canvas_sun.png';
moon.src = 'https://mdn.mozillademos.org/files/1443/Canvas_moon.png';
earth.src = 'https://mdn.mozillademos.org/files/1429/Canvas_earth.png';
window.requestAnimationFrame(draw);
}
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);
window.requestAnimationFrame(draw);
}
init();