canvas的状态就是当前画面应用的所有样式和变形的一个快照。
canvas的状态存储在栈中。
一个绘画状态包括:
该方法保存画布canvas的所有状态。该方法可以任意多次被调用,每当save()方法被调用后,当前的状态就被推进到栈中保存。
该方法恢复canvas的上一个保存的状态,并应用到后续的绘画中。
每当restore()方法被调用后,上一个保存的状态就从栈中弹出,所有canvas画布当前的配置都恢复为弹出的状态中保存的配置,并在后续图像绘制中得以应用。
如果觉得难以理解,请结合下面的综合示例进行理解。
示例效果:
实现代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Canvas 状态的保存与恢复 </title>
<style>
body {
height: 100vh;
padding: 10px;
}
</style>
<script>
function draw() {
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
const ctx = canvas.getContext('2d');
ctx.fillRect(0, 0, 150, 150);
ctx.save(); // 第一次保存状态
ctx.fillStyle = '#09F';
ctx.fillRect(15, 15, 120, 120);
ctx.save(); // 第二次绘制状态
ctx.fillStyle = '#FFF';
ctx.globalAlpha = 0.5;
ctx.fillRect(30, 30, 90, 90);
ctx.restore(); // 恢复第二次保存的状态,并应用到后续的绘画中
ctx.fillRect(45, 45, 60, 60);
ctx.restore(); // 恢复第一次保存的状态,并应用到后续的绘画中
ctx.fillRect(60, 60, 30, 30);
} else {
alert('您的浏览器不支持Canvas!');
}
}
</script>
</head>
<body onload="draw();">
<canvas id="canvas" width="300" height="300" style="background-color: #f3f4f8; color: chocolate"></canvas>
</body>
</html>
移动是通过 translate()
方法来移动canvas和它的原点到一个不同的位置。
translate(x, y)
translate方法接受两个参数,x是左右偏移量,y 是上下偏移量。
示例:
实现代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Canvas 移动 translate </title>
<style>
body {
height: 100vh;
padding: 10px;
}
</style>
<script>
function draw() {
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
const ctx = canvas.getContext('2d');
for (let i = 0; i < 7; i++) {
for (let j = 0; j < 7; j++) {
ctx.save();
ctx.fillStyle = `rgb(${51 * i}, ${255 - 51 * i}, 255)`;
ctx.translate(10 + j * 50, 10 + i * 50);
ctx.fillRect(0, 0, 25, 25);
ctx.restore();
}
}
} else {
alert('您的浏览器不支持Canvas!');
}
}
</script>
</head>
<body onload="draw();">
<canvas id="canvas" width="300" height="300" style="background-color: #f3f4f8; color: chocolate"></canvas>
</body>
</html>
代码解析:
这个例子显示了一些移动 canvas 原点的好处。如果不使用 translate 方法,那么所有矩形都将被绘制在相同的位置(0,0)。translate 方法同时让我们可以任意放置这些图案,而不需要在 fillRect() 方法中手工调整坐标值,既好理解也方便使用。
旋转是以原点为中心旋转canvas,如果要改变它,则需要用到上面介绍的translate()方法。
rotate(angle)
这个方法只接受一个参数:旋转的角度 (angle),它是顺时针方向的,以弧度为单位的值。
旋转rotate()方法的参数angle的单位是弧度,比较难以理解和感知,相对而言,角度对我们来说就很容易理解感知了,比如我们所熟悉的读书30度,45度等。那么我们可以通过数学公式来进行转换。
将角度转换为弧度的计算公式:弧度 = (Math.PI / 180) * 角度
示例:
实现代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Canvas 旋转 rotate </title>
<style>
body {
height: 100vh;
padding: 10px;
}
</style>
<script>
function draw() {
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
const ctx = canvas.getContext('2d');
ctx.save();
ctx.fillStyle = '#F00';
ctx.translate(100, 100);
ctx.fillRect(0, 0, 100, 100);
ctx.globalAlpha = 0.5;
ctx.rotate((Math.PI / 180) * 45);
// ctx.translate(-100, -100);
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, 140, 140);
} else {
alert('您的浏览器不支持Canvas!');
}
}
</script>
</head>
<body onload="draw();">
<canvas id="canvas" width="300" height="300" style="background-color: #f3f4f8; color: chocolate"></canvas>
</body>
</html>
缩放方法scale()的语法如下:
scale(x, y)
scale方法可以缩放画布的水平和垂直的单位。两个参数都是实数,可以为负数,x 为水平缩放因子,y 为垂直缩放因子,如果比 1 小,会缩小图形,如果比 1 大会放大图形。默认值为 1,为实际大小。
示例:(下面的效果中缩放后,坐标发生变化,这里不明白,后面再找时间研究吧)
实现代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Canvas 缩放 scale </title>
<style>
body {
height: 100vh;
padding: 10px;
}
</style>
<script>
function draw() {
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
const ctx = canvas.getContext('2d');
ctx.save();
ctx.fillRect(10, 10, 30, 30); // 对比
ctx.scale(2, 1);
ctx.globalAlpha = 0.5;
ctx.fillRect(10, 40, 30, 30); // 缩放效果
ctx.restore();
ctx.fillRect(10, 70, 30, 30); // 对比
} else {
alert('您的浏览器不支持Canvas!');
}
}
</script>
</head>
<body onload="draw();">
<canvas id="canvas" width="300" height="300" style="background-color: #f3f4f8; color: chocolate"></canvas>
</body>
</html>
通过transform()方法对变形矩阵进行修改,语法如下:
transform(a, b, c, d, e, f)
6个参数含义如下:
介绍两个设置(重置)当前变形矩阵为单位矩阵的方法:
setTransform(a, b, c, d, e, f)
resetTransform() // 该方法相当于 setTransform(1, 0, 0, 1, 0, 0)
示例:
实现代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Canvas 变形 transform </title>
<style>
body {
height: 100vh;
padding: 10px;
}
</style>
<script>
function draw() {
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
const ctx = canvas.getContext('2d');
const sin = Math.sin(Math.PI / 6);
const cos = Math.cos(Math.PI / 6);
ctx.translate(100, 100);
let c = 0;
for (let i = 0; i <= 12; i++) {
c = Math.floor((255 / 12) * i);
ctx.fillStyle = "rgb(" + c + "," + c + "," + c + ")";
ctx.fillRect(0, 0, 100, 10);
ctx.transform(cos, sin, -sin, cos, 0, 0);
}
ctx.setTransform(-1, 0, 0, 1, 100, 100);
ctx.fillStyle = "rgba(255, 128, 255, 0.5)";
ctx.fillRect(0, 2, 100, 100);
} else {
alert('您的浏览器不支持Canvas!');
}
}
</script>
</head>
<body onload="draw();">
<canvas id="canvas" width="300" height="300" style="background-color: #f3f4f8; color: chocolate"></canvas>
</body>
</html>
上面的示例中用到JavaScript的Math库的数据函数,从而实现了复杂且高级的效果,后续会补充一些相关函数的介绍,将会有利于我们实现一些高级效果。