Skip to content

Canvas 的基本用法

Canvas API 提供了一个通过 JavaScriptHTML<canvas> 元素来绘制图形的方式。它可以用于动画、游戏画面、数据可视化、图片编辑以及实时视频处理等方面。
Canvas API 主要聚焦于 2D 图形。而同样使用<canvas>元素的 WebGL API 则用于绘制硬件加速的 2D 和 3D 图形。

<canvas> 元素

html
<canvas id="canvas" width="150" height="150"></canvas>

<canvas> 看起来和 <img> 元素很相像,唯一的不同就是它并没有 src 和 alt 属性。实际上,<canvas> 标签只有两个属性 width 和 height。这些都是可选的。当没有设置宽度和高度的时候,canvas 会初始化宽度为 300 像素和高度为 150 像素。该元素可以使用 CSS 来定义大小,但在绘制时图像会伸缩以适应它的框架尺寸:如果 CSS 的尺寸与初始画布的比例不一致,它会出现扭曲。

备注:

如果绘制出来的图像是扭曲的,尝试用 width 和 height 属性为<canvas>明确规定宽高,而不是使用 CSS。

替换内容

<canvas>元素与<img>标签的不同之处在于,就像<video><audio>,或者<picture>元素一样,很容易定义一些替代内容。由于某些较老的浏览器(尤其是 IE9 之前的 IE 浏览器)或者文本浏览器不支持 HTML 元素"canvas",在这些浏览器上应该展示替代内容。

<canvas>标签中提供了替换内容。不支持<canvas>的浏览器将会忽略容器并在其中渲染后备内容。而支持<canvas>的浏览器将会忽略在容器中包含的内容,并且只是正常渲染 canvas。

html
<canvas id="canvas" width="150" height="150"> 当前浏览器不支持canvas标签 </canvas>

</canvas> 标签不可省

<img> 元素不同,<canvas> 元素需要结束标签 (</canvas>)。如果结束标签不存在,则文档的其余部分会被认为是替代内容,将不会显示出来。

渲染上下文

<canvas> 元素创造了一个固定大小的画布,它暴露一个或多个渲染上下文,其可以用来绘制和处理要展示的内容。

canvas 起初是空白的。为了展示,首先脚本需要找到渲染上下文,然后在它的上面绘制。<canvas> 元素有一个 getContext() 方法,这个方法是用来获得渲染上下文和它的绘画功能。getContext()接受一个参数,即上下文的类型。对于 2D 图像而言,可以使用 CanvasRenderingContext2D

js
var canvas = document.getElementById('canvas')
var ctx = canvas.getContext('2d')

代码的第一行通过使用 document.getElementById() 方法来为 <canvas> 元素得到 DOM 对象。一旦有了元素对象,可以通过使用它的 getContext() 方法来访问绘画上下文。

在 vue3 中

html
<canvas ref="canvas"></canvas>

js
import { ref, onMounted } from 'vue'
const canvas = ref() 
onMounted(() => {
  const ctx = canvas.value.getContext('2d') 
})

在微信小程序中

说明:显示为html类型只是用于语法高亮,微信小程序中该文件类型为wxml
html
<canvas type="2d" id="canvas"></canvas>

js
this.createSelectorQuery()
  .select('#canvas')
  .fields({
    node: true,
    size: true,
  })
  .exec(this.getCanvasInfo.bind(this))

getCanvasInfo(res) {  //  该方法在methods中定义
  const canvas = res[0].node  // Canvas 对象
  const ctx = canvas.getContext('2d')  // 渲染上下文
}

一个简单例子

绘制了两个长方形,其中的一个有着 alpha 透明度。

示例代码

js
const ctx = canvas.value.getContext('2d')
ctx.fillStyle = 'rgb(200,0,0)'
ctx.fillRect(10, 10, 55, 50)

ctx.fillStyle = 'rgba(0, 0, 200, 0.5)'
ctx.fillRect(30, 30, 55, 50)