1 什么是canvas
canvas是一个HTML新元素,可被JavaScript语言来绘制图形。HTML5中,canvas标签是一个矩形区域,包含了width和height,都可以通过CSS来定义,其默认值为300px和150px。在网页中使用的形式如下:
<canvas id="mycanvas" width="300" height="200" style="border:1px solid #c3c3c3">
Your browser doesn't support the canvas element.
</canvas>
属性值 | 说明 |
id | 画布对象名称 |
width | 宽度 |
height | 高度 |
style | CSS样式,表示画布的样式 |
画布canvas本身不具有绘制图形的功能,只是一个容器。但我们放置好canvas画布元素,我们就可以使用脚本语言JavaScript在网页上绘制图像,使用JavaScript来绘制图形的步骤如下:
- ① JavaScript使用id来寻找canvas元素,即获取当前画布对象:
var c = document.getElementById("mycanvas")
- ② 创建context对象:
var cxt = c.getContext("2d")
getContext方法返回的是一个指定的contextId的上下文对象,若指定的id不被支持,则返回null,当前被强制必须支持的是2D,将来会有3D,注意id大小写敏感。对象cxt建立后,就可以拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法。
- ③ 绘制图形:
cxt.fillStyle = "#FF0000";
cxt.fillRect(0,0,150,75)
fillStyle方法将其染成红色,fillRect方法规定了形状、位置和尺寸。此为绘制红色矩形的代码。
2 绘制基本形状
2.1 绘制矩形
单独的canvas标记只是在页面中定义了一块矩形区域,需要配合JavaScript脚本才能绘制各种图形、线条和其它复杂的图形。与SVG来实现同样绘图效果来比较,canvas是像素级别的绘图技术,SVG是一种矢量的绘图技术。
canvas绘制矩形的方法
方法 | 说明 |
fillStyle | 用于设定填充的颜色,透明度等。rgb不可透明,rgba课透明 |
fillRect | 绘制一个矩形,无边框,只有填充色。这个方法有四个参数,前两个参数表示左上角的坐标位置,第三个为长度,第四个为高度 |
strokeRect | 绘制一个边框的矩形,有四个参数,使用方法同上 |
clearRect | 清除一个矩形区域,被清除的区域将无任何线条,有四个参数,使用方法同上 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>绘制矩形</title>
</head>
<body>
<canvas id="juxing" width="300" height="200" style="border:1px solid blue">
Your browser doesn't support the canvas element.
</canvas>
<script type="text/javascript">
var c = document.getElementById("juxing");
var cxt = c.getContext("2d");
cxt.fillStyle = "rgba(200,0,0,0.5)";
cxt.fillRect(10,20,100,100);
</script>
</body>
</html>
2.2 绘制圆形
基于canvas绘图并不是直接在canvas标记说创建的绘图画面上进行各种绘图操作,而是依赖画面提供的渲染上下文,所有的绘图命令和属性都定义在渲染下文中。渲染上下文与canvas一一对应,无论对同一canvas对象调用几次getContext()方法,都将返回同一个上下文对象。
canvas绘制圆形的方法
方法 | 说明 |
fillStyle | 用于设定填充的颜色,透明度等。rgb不可透明,rgba课透明 |
beginPath() | 开始绘制路径 |
arc(x,y,radius,startAngle,endAngle,anticlockwise) | x和y定义圆的原点;radius是圆的半径;startAngle和endAngle定义开始弧度和结束弧度;anticlockwise用来定义画圆的方向,值为true和false |
closePath() | 结束路径的绘制 |
fill() | 进行填充 |
stroke() | 设置边框 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>绘制矩形</title>
</head>
<body>
<canvas id="juxing" width="300" height="200" style="border:1px solid blue">
Your browser doesn't support the canvas element.
</canvas>
<script type="text/javascript">
var c = document.getElementById("juxing");
var cxt = c.getContext("2d");
cxt.fillStyle = "rgba(00,300,200,0.5)";
cxt.beginPath();
cxt.arc(70,70,50,0,Math.PI*2,true);
cxt.closePath();
cxt.fill();
cxt.stroke();
</script>
</body>
</html>
2.3 使用moveTo与lineTo绘制直线
每个canvas实例对象中都有以一个path对象,创建自定义图形的过程就是不断对path对象进行操作的过程。每当开始一次新的图形绘制任务,都需要先使用begainPath()方法来重置path对象至初始状态,进而通过一系列对moveTo/lineTo等划线方法的调用,绘制出期望的路径,moveTo(x,y)方法设置绘图起始坐标,lineTo(x,y)等划线方法可以从当前起点绘制直线、圆弧和曲线到目标位置。最后调用(可选)closePath()方法将自定义图形进行闭合,该方法将自动创建一条从当前坐标到起始坐标的直线。
canvas绘制直线的方法
方法 | 说明 |
moveTo(x,y) | 不绘制,只是将当前位置移动到性目标坐标(x,y),作为线条开始点 |
lineTo(x,y) | 从设置的开始点绘制到指定的目标坐标(x,y),并在两坐标之间画一条直线。无论调用哪一个,都不会真正的绘制出图形,因为还未调用stroke(绘制)和fill(填充)。只是定义路径的位置,以便绘制时调用。 |
strockStyle | 指定线条的颜色 |
lineWidth | 设置线条的粗细 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>绘制矩形</title>
</head>
<body>
<canvas id="juxing" width="800" height="600" style="border:1px solid blue">
Your browser doesn't support the canvas element.
</canvas>
<script type="text/javascript">
var c = document.getElementById("juxing");
var cxt = c.getContext("2d");
cxt.beginPath();
cxt.strokeStyle = "rgb(0,182,3)";
cxt.moveTo(200,150);
cxt.lineTo(400,450);
cxt.lineTo(600,150);
cxt.lineWidth = 20;
cxt.stroke();
cxt.closePath();
cxt.fillStyle = "red"
cxt.fill();
</script>
</body>
</html>
2.4 使用bezierCurveTo绘制贝济埃曲线
bezierCurveTo用法:
bezierCruveTo(cpx1,cpy1,cpx2,cpy2,x,y)
参数 | 描述 |
cpx1,cpy1 | 和曲线的开始点(当前位置点)相关联的控制点的坐标 |
cpx2,cpy2 | 和曲线结束点相关联控制点的坐标 |
x,y | 曲线结束点的坐标 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>贝济埃曲线的绘制</title>
<script>
function draw(id)
{
var canvas = document.getElementById(id);
if (canvas == null)
return false;
var context = canvas.getContext("2d");
context.fillStyle = "#eeeeff";
context.fillRect(0,0,400,300);
var n = 0;
var dx = 150;
var dy = 150;
var s = 100;
context.beginPath();
context.globalCompositeOperation = "and";
context.fillStyle = 'rgb(300,255,0)';
context.strokeStyle = "rgb(0,0,100)";
var x = Math.sin(0);
var y = Math.cos(0);
var dig = Math.PI / 15 * 11;
for (var i = 0;i<30;i++)
{
var x = Math.sin(i*dig);
var y = Math.cos(i*dig);
context.bezierCurveTo(dx+x*s,dy+y*s-100,dx+x*s+100,dy+y*s,dx+x*s,dy+y*s);
}
context.closePath();
context.fill();
context.stroke();
}
</script>
</head>
<body onload="draw('canvas');">
<h1>绘制元素</h1>
<canvas id="canvas" width="400" height="300"></canvas>
</body>
</html>
3 绘制渐变图形
渐变是两种或者更多颜色的平滑过渡,是指在颜色集上使用逐步抽布的算法,并将结果应用于描边样式和填充样式中。canvas的绘图支持线性渐变与放射性渐变(径向渐变)。
3.1 绘制线性渐变
- ① 创建渐变对象
var grandient = cxt.createLinearGradient(0,0,0,canvas.height);
- ② 为创建渐变对象设置颜色(也可以设置alpha值,设置透明度),指明过渡方式
gradient.addColorStop(0,"#fff");
gradient.addColorStop(1,"#000");
- ③ 在context上为填充样式或者描边设置渐变
cxt.fillStyle = gradient;
绘制线性渐变的方法
方法 | 功能 |
addColorStop | 函数允许设置两个参数:偏移量和颜色。偏移量是一个由0.0到1.0之间的数值,代表沿着渐变线渐变的距离有多远。颜色参数是在偏移位置或填充时所使用的颜色 |
createLinearGradient(x0,y0,x1,y1) | 沿着直线从(x0,y0)至(x1,y1)绘制渐变。 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LinearGradient</title>
</head>
<body>
<h2 align="center" style="color: #1B85E2">绘制线性渐变</h2>
<canvas id="cc" width="400" height="300" style="border:1px solid orangered"></canvas>
<script type="text/javascript">
var c = document.getElementById("cc");
var cxt = c.getContext("2d");
var gradient = cxt.createLinearGradient(0,0,0,cc.height);
gradient.addColorStop(0,"#fff");
gradient.addColorStop(1,"rgba(255,0,0,0.5)");
cxt.fillStyle = gradient;
cxt.fillRect(0,0,400,300)
</script>
</body>
</html>
3.2 绘制径向渐变
与线性不同之处在于实现径向渐变用createRadialGradient(x0,y0,r0,x1,y1,r1)来实现两个圆之间的锥面绘制渐变。其中前三个参数代表开始的圆,圆心为(x0,y0),半径为(r0);后三个参数代表结束的圆,圆心为(x1,y1),半径为r1。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LinearGradient</title>
</head>
<body>
<h2 align="center" style="color: #1B85E2">绘制线性渐变</h2>
<canvas id="cc" width="400" height="300" style="border:1px solid orangered"></canvas>
<script type="text/javascript">
var c = document.getElementById("cc");
var cxt = c.getContext("2d");
var gradient = cxt.createRadialGradient(cc.width/2,cc.height/2,0,cc.width/2,cc.height/2,200);
gradient.addColorStop(0,"#fff");
gradient.addColorStop(1,"rgba(255,0,0,1)");
cxt.fillStyle = gradient;
cxt.fillRect(0,0,400,400)
</script>
</body>
</html>
4 绘制变形图形
4.1 变换原点坐标
平移(translate),将绘图区相对于当前画布的左上角进行平移,若不进行变形,绘图区的原点和画布原点是重合的。若果进行变形,这坐标位置会移动到一个新位置。用translate(x,y)实现在平面上平移,其原来的原点的,然后偏移的位置为坐标原点。即原来的点为(10,10),translate(10,10)后的坐标原点就在(20,20)。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>变换原点坐标</title>
<script>
function draw(id)
{
var canvas = document.getElementById(id);
if (canvas == null)
return false;
var context = canvas.getContext("2d");
context.fillStyle = "#eeeeff";
context.fillRect(0,0,400,300);
context.translate(200,50);
context.fillStyle = 'rgba(255,0,0,0.25)';
for (var i=0;i<50;i++){
context.translate(25,25);
context.fillRect(0,0,100,50);
}
}
</script>
</head>
<!--cc双引号出错?why?-->
<body onload="draw('cc')">
<h1 align="center" style="color: red">变换原点坐标</h1>
<canvas id="cc" width="400" height="300"></canvas>
</body>
</html>
4.2 图形缩放
图形缩放就是对图像的宽和高的调整,通过使用scale(x,y)函数来实现缩放,如当x=2时,表示将绘制的图像中全部元素都会变成2倍宽;当y=0.5,则会变为之前的一半高。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>变换原点坐标</title>
<script>
function draw(id)
{
var canvas = document.getElementById(id);
if (canvas == null)
return false;
var context = canvas.getContext("2d");
context.fillStyle = "#eeeeff";
context.fillRect(0,0,400,300);
context.translate(200,50);
context.fillStyle = 'rgba(255,0,0,0.25)';
for (var i=0;i<50;i++){
context.scale(2,0.8);
context.fillRect(0,0,100,50);
}
}
</script>
</head>
<!--cc双引号出错?why?-->
<body onload="draw('cc')">
<h1 align="center" style="color: red">变换原点坐标</h1>
<canvas id="cc" width="400" height="300"></canvas>
</body>
</html>
4.3 旋转图形
rotate(弧度),默认从左上端的(0,0)开始旋转,通过制定一个角度改变了画布的坐标和浏览器元素的映射,使任意后续会与在画布中都显示为选装的,并没有旋转canvas元素。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>变换原点坐标</title>
<script>
function draw(id)
{
var canvas = document.getElementById(id);
if (canvas == null)
return false;
var context = canvas.getContext("2d");
context.fillStyle = "#eeeeff";
context.fillRect(0,0,400,300);
context.translate(200,50);
context.fillStyle = 'rgba(255,0,0,0.25)';
for (var i=0;i<50;i++){
context.rotate(Math.PI / 4);
context.fillRect(0,0,10,50);
}
}
</script>
</head>
<!--cc双引号出错?why?-->
<body onload="draw('cc')">
<h1 align="center" style="color: red">变换原点坐标</h1>
<canvas id="cc" width="400" height="300"></canvas>
</body>
</html>
5 绘制其它样式的图形
5.1 图形组合
globalCompositeOperation = type的方法
type方法 | 说明 |
source-over(默认) | 默认设置,新图形会覆盖在原有内容上 |
destination | 会在原有内容之下绘制新图形 |
source-in | 新图形会仅仅出现与原有内容重叠的部分,其余区域变为透明 |
destination-in | 原有内容中与新图形重叠的部分会被保留,其余区域会变为透明。同上相反 |
source-out | 结果只有新图形与原有图形不重叠的部分会被绘制出来 |
destination-out | 原有内容与新图形不重叠的部分会被保留 |
source-atop | 新图形与原有内容重叠的部分会被绘制,并覆盖于原有内容之上 |
destination-atop | 原有内容与新内容重叠部分会被保留,并会在原有内容之下绘制新图形 |
lighter | 两图形中重叠的部分会做加色处理 |
darker | 两图形重叠的部分会做减色处理 |
xor | 重叠的部分会变为透明 |
copy | 只有新图形会被保留,其余都会被清除 |
```html
Title ```
5.2 绘制带阴影的图形
阴影效果属性介绍
属性 | 说明 |
shadowOffsetX | 设置阴影x偏移量(水平),单位是px |
shadowOffsetY | 设置阴影y偏移量(垂直),单位是px |
shadowColor | 设置阴影颜色 |
shadowBlur | 设置阴影模糊程度,值越大阴影则越模糊 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>设置阴影效果</title>
</head>
<body>
<canvas id = "yinying" height="400" width="400" style="border:1px solid red"></canvas>
<script type="text/javascript">
var elem = document.getElementById('yinying');
if (elem && elem.getContext){
var context = elem.getContext('2d');
context.shadowOffsetX = 15;
context.shadowOffsetY = 15;
context.shadowColor = "rgba(255,0,0,0.5)"
context.shadowBlur = 10;
context.fillStyle = "#f00";
context.fillRect(100,100,200,200);
}
</script>
</body>
</html>
5.3 绘制文字
绘制文字的方法
方法属性 | 说明 |
fillText(text,x,y,maxwidth) | 绘制带fillStyle填充的文字(text),指定文本位置的坐标参数x、y,maxwidth是可选的,用于限制字体的大小,它会将文字强制收缩 |
trkeText(text,x,y,maxwidth) | 绘制只有strokeStyle边框的文字,其参数同上 |
measureText | 该函数会返回一个度量对象,其包含了在当前context环境下指定的文本 |
额外属性 | 说明(保证正常显示) |
font | 可以是CSS字体规则中的任何值。包括字体样式、变种、大小、粗细、行高和字体名 |
textAlign | 控制文本对齐方式,类似于CSS中的text-align,但不完全相同,取值有left、right、start、end和center |
textBaseline | 控制文本相对于起点的位置,取值有top、hanging、middle、alphabetic、ideogrphic和buttom() |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>设置阴影效果</title>
</head>
<body>
<canvas id = "yinying" height="400" width="400" style="border:1px solid red"></canvas>
<script type="text/javascript">
var elem = document.getElementById('yinying');
if (elem && elem.getContext){
var context = elem.getContext('2d');
context.fillStyle = "#f00";
context.font = 'italic 30px 微软雅黑';
context.textAlign = 'left';
context.textBaseline = "top";
context.fillText("生日快乐",20,20,50);
context.font = "bold 30px sans-serif ";
context.strokeText("生日快乐",50.50,100)
}
</script>
</body>
</html>
6 使用图像
6.1 绘制图像
在canvas画布上绘制图像,需要先有一个图片,该图片可以是已经存在的img元素,也可以是通过js创建的图片。**无论是哪种方式,都需要在绘制之前,完全加载这张图片。**若果图片未完全加载之前就将其呈现在canvas上,那么canvas就不会显示任何图片。
drawImage绘制图像的方法
方法 | 说明 |
drawImage(image,dx,dy) | 接受一个图片,并将其绘制在canvas中。给出的坐标(dx,dy)代表图片的左上角。(0,0)表示将图片从左上角开始绘制。 |
drawImage(image,dx,dy,dw,dh) | 接受一个图片,并将其缩范围宽度dw和高度dh,然后把他绘制到canvas的(dx,dy)处 |
drawImage(image,sx,sy,sw,sh,dx,dy,dw,dh) | 接受一个图片,通过参数(sx,sy,sw,sh)指定图片裁剪得到的范围,然后将其缩放到(dw,dh)的大小,最后将其绘制于canvas的(dx,dy)位置处 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>绘制图像</title>
</head>
<body>
<canvas id="drawimg" width="1000" height="1000" style="border:1px red solid"></canvas>
<script type="text/javascript">
window.onload = function () {
var ctx = document.getElementById('drawimg').getContext('2d');
var img = new Image();
img.src = "https://tse1-mm.cn.bing.net/th/id/OIP.t2yFncG6fQW_ESyvL8vAWgHaFj?pid=Api&rs=1";
img.onload=function () {
ctx.drawImage(img,10,10,40,40,100,100,300,300)
}
}
</script>
</body>
</html>
使用窗口的onload加载事件,即页面加载时的执行函数。于函数中,ctx为上下文对象,创建Image对象img;使用img对象的属性src设置图片来源,最后用draw画出当前的画像。
6.2 图像平铺
使用画布绘制图像,还可以将绘制的图像作为背景图使用。在做背景图片时,若果显示图片的区域不能直接设定,则可以通过调用cratePattern(img,type)函数来替换drawImage函数来实现平铺显示。
平铺type类型
参数值 | 说明 |
np-repeat | 不平铺 |
repeat-x | 横向平铺 |
repeat-y | 纵向平铺 |
repeat | 全方向平铺 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>图形平铺</title>
</head>
<body onload="draw('repeatimg')">
<canvas id="repeatimg" width="500" height="500" style="border: #1B85E2 1px solid"></canvas>
<script type="text/javascript">
function draw(id) {
var canvas = document.getElementById('repeatimg');
if (canvas == null) {
return false;
}
var context = canvas.getContext('2d');
context.fillStyle = "rgb(255,0,0)";
context.fillRect(100,100,200,200)
img = new Image();
img.src = "https://tse2-mm.cn.bing.net/th/id/OIP.-JGAn0aniXgqzATzxc5WfgHaHQ?pid=Api&rs=1";
img.onload = function () {
var ptrn = context.createPattern(img,"repeat")
context.fillStyle = ptrn;
context.fillRect(100,100,500,500)
}
}
</script>
</body>
</html>
6.3 图像裁剪
处理图像时经常会遇到裁剪这种需求,即在画布上裁剪出一块区域,这块区域是在裁剪动作之前,由绘图路径设定的,可以是正方形、圆形、五角星和其它多边形来绘制的轮廓。即裁剪路径即为绘图路径,只不过这个路径不是用来绘图的,而是用来设定显示区域和遮挡区域的分界线。利用clip给canvas设置一个裁剪区域,在调用clip方法之后的代码只对这个设定的裁剪区域有效,不会影响其它地方,在局部更新时很有用。默认情况下裁剪区域为左上角(0,0),宽和高分别等于canvas元素的宽和高的矩形。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>图像裁剪</title>
<script type="text/javascript" src="script.js"></script>
</head>
<body onload="draw('clip')">
<h1>图像裁剪实例</h1>
<canvas id="clip" width="500" height="500" style="border: aqua 2px solid"></canvas>
<script>
function draw(id) {
var canvas = document.getElementById(id);
if (canvas == null){
return false;
}
var context = canvas.getContext('2d');
// 创建线性渐变线
var gr = context.createLinearGradient(0,400,300,0);
gr.addColorStop(0,"rgba(255,0,0,0.5)");
gr.addColorStop(1,"rgba(0,255,255,0.5)");
context.fillStyle = gr;
context.fillRect(0,0,500,500);
img = new Image();
img.onload = function () {
// 后面编写的一个函数名,非drawImage函数
drawImg(context,img);
}
img.src = "01.jpg";
}
function drawImg(context,img) {
// 多边图形创建
create8StarClip(context);
context.drawImage(img,-50,-150,300,300);
}
function create8StarClip(context){
var dx=100;
var dy=0;
var s=150;
context.beginPath();
context.translate(100,150);
var x=Math.sin(0);
var y=Math.cos(0);
var dig=Math.PI/5*4;
for(var i=0;i<10;i++){
var x=Math.sin(i*dig);
var y=Math.cos(i*dig);
context.lineTo(dx+x*s,dy+y*s);
}
context.clip();
}
</script>
</body>
</html>
6.4 像素处理
电脑屏幕上的图像都是由一个个像素点组成的,一个像素对应这内存中一组连续的二进制位,每个位上的取值只能是0和1,连续的二进制位就可以由0和1排列组合出很多情况,每一组排列组合决定了像素的一种颜色。每个像素点由四个字节构成,第一个决定了像素的红色值,第二个决定了像素的路设值,第三个决定了像素的蓝色值,第四个决定了像素的透明度值。
在canvas画布中,可以使用ImageData对象来保存,有width、height和data三个属性,其中data属性是一个连续数组,图像中所有像素其实都保存在data中。
图像像素处理方法
方法 | 说明 |
createImageData(width,height) | 在内存中创建一个指定ImageData(像素数组)对象,对象中的像素点是黑色透明的,即rgb(0,0,0,0) |
createImageData(x,y,width,height) | 返回一个ImageData对象,包含了指定区域的像素数组 |
putImageData(data,x,y) | 将ImageData对象绘制到屏幕指定区域上 |
<!-- @TIME: 2020/9/21 14:59-->
<!-- @Author: 悠悠我心ya-->
<!-- @File: 像素处理.py-->
<!-- Software: PyCharm-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>图像像素处理</title>
<script type="text/javascript" src="script.js"></script>
</head>
<body onload="draw('xs')">
<h1>图像像素处理</h1>
<canvas id="xs" width="500" height="500" style="border: indigo 1px solid;"></canvas>
<script>
function draw(id) {
var canvas = document.getElementById(id);
if (canvas == null){
return false;
}
var context = canvas.getContext('2d');
img = new Image();
img.src = "01.jpg";
img.onload = function () {
context.drawImage(img,0,0);
var imgdata = context.getImageData(0,0,img.width,img.height);
for (var i=o,n=imgdata.data.length;i<n;i+=4){
imgdata.data[i+0] = 255 - imgdata.data[i+2];
imgdata.data[i+1] = 255 - imgdata.data[i+1];
imgdata.data[i+2] = 255 - imgdata.data[i+0] ;
}
context.putImageData(imgdata,0,0)
}
}
</script>
</body>
</html>
7 图形的保存与恢复
7.1 保存与恢复状态
画布中,由两个方法管理绘制状态的当前栈,save方法把当前状态放入栈中,而restore从栈顶弹出状态,绘制状态不会覆盖对画布所做的每件事情。save方法用来保存canvas的状态,save之后可以调用canvas的平移、放缩等操作。restore用于恢复canvas之前保存的状态,放置save后对canvas后续操作有影响。save和restore要配对使用,需要注意的是restore调用的次数需要少于save的次数,否则出错。
<!-- @TIME: 2020/9/21 23:53-->
<!-- @Author: 悠悠我心ya-->
<!-- @File: 保存与恢复.py-->
<!-- Software: PyCharm-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>保存与恢复</title>
</head>
<body>
<canvas id="sr" height="500" width="500" style="border: 1px rebeccapurple solid"></canvas>
<script type="text/javascript">
var c = document.getElementById("sr");
var cxt = c.getContext("2d");
cxt.fillStyle = "rgb(255,0,0)";
cxt.save();
cxt.fillRect(50,50,100,100);
cxt.fillStyle = "rgb(0,0,255)";
cxt.save();
cxt.fillRect(200,50,100,100);
cxt.restore();
cxt.fillRect(350,50,100,100);
cxt.restore();
cxt.fillRect(50,200,100,100);
</script>
</body>
</html>
7.2 保存文件
<!-- @TIME: 2020/9/21 23:53-->
<!-- @Author: 悠悠我心ya-->
<!-- @File: 保存与恢复.py-->
<!-- Software: PyCharm-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>保存与恢复</title>
</head>
<body>
<canvas id="sr" height="500" width="500" style="border: 1px rebeccapurple solid"></canvas>
<script type="text/javascript">
var c = document.getElementById("sr");
var cxt = c.getContext("2d");
cxt.fillStyle = "rgb(255,0,0)";
cxt.save();
cxt.fillRect(50,50,100,100);
cxt.fillStyle = "rgb(0,0,255)";
cxt.save();
cxt.fillRect(200,50,100,100);
cxt.restore();
cxt.fillRect(350,50,100,100);
cxt.restore();
cxt.fillRect(50,200,100,100);
window.location=cxt.canvas.toDataURL('image/png')
</script>
</body>
</html>