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>