JavaScript canvas

本文将介绍 canvas ,用于在 HTML 中绘图的标签。

一、什么是 canvas?

canvas 可以在网页上绘制图像、制作简单的动画、甚至进行实时视频处理和渲染。

HTML5 中新增了 canvas 标签,该标签用于定义图形容器。定义容器后使用 JavaScript 在容器之中绘制图像。

二、初始化 canvas

1
2
3
4
5
6
7
8
// 定义容器
<canvas id="myCanvas"></canvas>

// 找到容器
var canvas = document.getElementById('myCanvas');

// 创建context对象
var cx = canvas.getContext("2d");

三、canvas 标签

canvas 标签有两个可选属性:width、height,用于为 canvas 容器设置高度和宽度。

1
<canvas id="myCanvas" width="300" height="300"></canvas>

如果不给 canvas 设置 width 和 height,则默认 width 为 300,height 为 150。

此外,也可以通过 CSS 设置容器的高度和宽度。

需注意:

  • 标签中的 width 和 height 是画布的实际尺寸
  • CSS 中的 width 和 height 是画布在页面上放置的尺寸

因此,

如果标签中的尺寸更大,则画布会进行压缩;

如果 CSS 中的尺寸更大,则画面会进行拉伸。

非必要时,不必设置 CSS 尺寸。如果设置,应该使两对 width 和 height 的比例相等,防止出现拉伸/压缩变形。

四、常用命令

1. beginPath()

表明要开始一个新的路径,用于和之前绘制的路径相分隔。

1
2
3
4
5
6
7
8
9
10
11
12
13
// 开始路径
context.beginPath();
context.strokeStyle = 'blue';
context.moveTo(60, 20);
context.lineTo(220, 20);
context.stroke();
// 开始路径 again
context.beginPath();
context.strokeStyle = 'green';
context.moveTo(60, 20);
context.lineTo(160, 120);
context.stroke();
// 登录状态下不会出现这行文字,点击页面右上角一键登录

执行了 2 次 beginPath(),实时效果如下:

1
2
3
4
5
6
7
8
9
10
11
12
// 开始路径
context.beginPath();
context.strokeStyle = 'blue';
context.moveTo(60, 20);
context.lineTo(220, 20);
context.stroke();

context.strokeStyle = 'green';
context.moveTo(60, 20);
context.lineTo(160, 120);
context.stroke();
// 登录状态下不会出现这行文字,点击页面右上角一键登录

执行了 1 次 beginPath(),实时效果如下:

只要是非连续路径绘制,都应该在绘制新路径时调用 beginPath() 。

2. moveTo(x, y)

移动路径绘制的起始点至指定位置,即移动绘制起始点。

3. lineTo(x, y)

用于绘制直线,表示从绘制起始点移动至指定点。

4. arc()

用于绘制圆弧。

5. rect()

用于绘制矩形。

6. fillText(text, x, y)

用于以填充方式绘制文本。

7. strokeText(text, x, y)

用于以描边方式绘制文本。

8. drawImage()

用于绘制图像。

9. fill()

用于对路径进行填充。

10. stroke()

用于对路径进行描边。

11. closePath()

用于闭合路径,会将路径的最后位置与起始位置用直线相连。

四、绘制

1. 画线

1
2
3
4
cxt.moveTo(10,10);
cxt.lineTo(150,50);
cxt.lineTo(10,50);
cxt.stroke();

2. 画圆

1
2
3
4
5
cxt.fillStyle="#FF0000";
cxt.beginPath();
cxt.arc(70,18,15,0,Math.PI*2,true);
cxt.closePath();
cxt.fill();

3. 画图像

(1) 创建图片并绘制

1
2
3
var img = new Image()
img.src = "URL"
ctx.drawImage(img, 10, 10);

(2) 将已有图片放置到画布之上

1
2
3
4
5
<img id="scream"src="URL" alt="">
<canvas id="myCanvas"></canvas>


ctx.drawImage(document.getElementById("scream"), 10, 10);

五、 canvas 模糊问题

1. 问题

小屏幕设备和高分辨率屏幕往往会对屏幕进行缩放,这意味着浏览器会将多个像素渲染为一个像素。假设缩放比例为 1.5,则屏幕中的 1 个像素点将由 1.5 个像素点渲染而成,在浏览器进行渲染时,它会拿到 1.5 倍大小的元素,缩放至 1 倍后显示在屏幕上。但 canvas 在绘制时并不会因缩放比例而进行放大绘制(放大以便之后的缩放),而是严格按照标签的尺寸进行绘制,又因为 canvas 并不是矢量图,因此会在缩放中产生模糊。

2. 解决方法

有一个简单粗暴的解决方式:检测设备的像素比,并绘制对应倍数比例的 canvas 元素。如此一来,canvas 元素便可以被缩放而不产生模糊。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 将画布显示尺寸赋给css样式
<canvas id="myCanvas" style="width: 宽度;height: 高度"></canvas>

// 初始化 canvas
this.canvas = document.getElementById('canvas')
this.ctx = this.canvas.getContext('2d')
// 获取渲染比例
this.backingStore = this.ctx.backingStorePixelRatio
|| this.ctx.webkitBackingStorePixelRatio
|| this.ctx.mozBackingStorePixelRatio
|| this.ctx.msBackingStorePixelRatio
|| this.ctx.oBackingStorePixelRatio
|| this.ctx.backingStorePixelRatio
|| 1
this.ratio = (window.devicePixelRatio || 1) / backingStore
// 计算画布实际尺寸,并赋给元素
this.canvas.width = 宽度 * this.ratio
this.canvas.height = 高度 * this.ratio
// 将canvas绘制中的尺寸都乘以对应倍率
尺寸 * this.ratio

六、 vue 中使用 canvas

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<template>
<div>
<canvas id="canvas">
your browser does not support the canvas tag
</canvas>
</div>
</template>

<script>
export default {
name: '',
data() {
return {
// canvas
canvas: '',
// 用于在画布上绘图的环境
ctx: {},
}
},
mounted() {
// 初始化canvas
this.canvas = document.getElementById('canvas')
this.ctx = this.canvas.getContext('2d')
}
</script>

<style scoped>
</style>

​

参考