FE

初学 Canvas

Canvas 的功能和基本用法

Posted by nolan on February 26, 2020

一、概述

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');

栅格:

image

左上角为画笔(渲染上下文)的笔触,可以使用 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();

参考 MDN Canvas 教程