JavaScript canvas

简介

HTML5 <canvas> 是绘制 图形/图像 的容器。它本身并没有绘制能力,您必须使用脚本来完成实际的绘图任务(通常是 JavaScript)。

如果浏览器不支持<canvas>的话,会显示<canvas>标签内定义的元素。例如,下面代码在不支持的<canvas>浏览器下就会忽略<canvas>标签,显示<p>标签。

<canvas id="canvas" width="500" height="300" style="border:1px solid #aaa">
    <p>Your browser does not support the canvas element!</p>  
</canvas>

JavaScript 绘图准备

获取html中的 <canvas>元素

var canvas = document.getElementById("canvas");

创建绘图对象上下文

getContext(contextID) 方法可返回一个对象,该对象提供了用于在画布上绘图的方法和属性。该方法需要一个参数,一般是2d,即getContext(‘2d’)。这是为了将来扩展到3d画布保留的一个参数。

var ctx = canvas.getContext('2d');

这样就可以在画布上下文中绘制图案了。

JavaScript 绘制基本图形

颜色

  • fillStyle
    设置或返回用于填充绘画的颜色、渐变或模式。
  • strokeStyle
    设置或返回用于笔触的颜色、渐变或模式。
<html>
    <body>
        <canvas id="canvas" width="250" height="100" style="border:1px solid #aaa">
            <p>Your browser does not support the canvas element!</p>  
        </canvas>
        <script type="text/javascript">
            var canvas = document.getElementById('canvas');
            var ctx = canvas.getContext('2d');
            ctx.fillStyle='#f00';
            ctx.fillRect(10,10,100,50);
            ctx.strokeStyle="#0f0"
            ctx.strokeRect(130,10,100,50);
        </script>
    </body>
</html>

这里写图片描述

渐变

  • gradient.addColorStop(stop,color)
    规定 gradient 对象中的颜色和位置。
    • stop 介于 0.0 与 1.0 之间的值,表示渐变中开始与结束之间的位置。
    • color 在结束位置显示的 CSS 颜色值。
  • createLinearGradient(x0, y0, x1, y1)
    创建线性渐变。渐变可用于填充矩形、圆形、线条、文本等等。
    小于 (x0, y0) 与 (x1, y1) 连线在 (x0, y0) 点的垂线的区域填充stop=0 的纯色。大于 (x0, y0) 与 (x1, y1) 连线在 (x1, y1) 点的垂线的区域填充stop=1 的纯色。
  • createRadialGradient(x0, y0, r0, x1, y1, r1)
    创建放射状/环形的渐变。渐变可用于填充矩形、圆形、线条、文本等等。
    半径大的一定在下层,半径小的一定在上层,和顺序无关。渐变区域为两圆相连的中间区域。由于指定的是绝对坐标,因此一定要保证最大的那个渐变半径大于绘制区域,否则大半径范围之外的绘制区域不会产生任何效果。
  • createPattern(img, direction)
    在指定的方向上重复指定的元素。被重复的元素可用于绘制/填充矩形、圆形或线条等等。
    pattern按图片的大小从(0, 0)点开始绘制,因此如果direction != repeat,一定要确保它绘制在显示范围中
    • img
      规定要使用的图片、画布或视频元素。
    • direction
      • repeat
        默认。该模式在水平和垂直方向重复。
      • repeat-x
        该模式只在水平方向重复。
      • repeat-y
        该模式只在垂直方向重复。
      • no-repeat
        该模式只显示一次(不重复)。
<html>
    <head>
        <style type="text/css">
            button {
                width:150px;
            }
        </style>
        <script type="text/javascript">
            function drawLinearGradient() {
                var c = document.getElementById("canvas");
                var ctx = c.getContext("2d");
                var linearGradient = ctx.createLinearGradient(0, 0, 100, 100);
                linearGradient.addColorStop(0, "red");
                linearGradient.addColorStop(.5, "rgb(0,255,0)");
                linearGradient.addColorStop(1, "#00f");
                ctx.clearRect(0, 0, c.width, c.height);
                ctx.fillStyle = linearGradient;
                ctx.fillRect(0,0,50,50);
                ctx.fillRect(50,0,100,100);
                ctx.fillRect(150,0,200,200);
            }
            function drawPattern(direction) {
                var c = document.getElementById("canvas");
                var ctx = c.getContext("2d");
                var img = document.getElementById("grass");
                var pattern = ctx.createPattern(img, direction);
                ctx.clearRect(0, 0, c.width, c.height);
                ctx.fillStyle = pattern;
                ctx.fillRect(0, 0, 200, 200);

                ctx.strokeStyle = pattern;
                ctx.lineWidth = 20;
                ctx.beginPath();
                ctx.moveTo(0,220);
                ctx.lineTo(200,220);
                ctx.stroke();

                ctx.beginPath();
                ctx.arc(100,300,50,0,2*Math.PI);
                ctx.stroke();
            }
            //渐变半径大的在下层,小的在上层
            function drawRadialGradient() {
                var c = document.getElementById("canvas");
                var ctx = c.getContext("2d");
                ctx.lineWidth=3;
                var radialGradient = ctx.createRadialGradient(50,50,30,100,100,70);
                radialGradient.addColorStop(0, "red");
                radialGradient.addColorStop(.5, "rgb(0,255,0)");
                radialGradient.addColorStop(1, "#00f");
                ctx.fillStyle = radialGradient;
                ctx.clearRect(0, 0, c.width, c.height);
                ctx.fillRect(0, 0, 200, 200);
                ctx.strokeStyle = "yellow";
                ctx.strokeRect(0, 0, 200, 200);

                //必须beginPath和stroke结束线段,否则它们是连在一起的
                ctx.beginPath();
                ctx.arc(50,50,30,0,2*Math.PI);
                ctx.stroke();
                ctx.beginPath();
                ctx.arc(75,75,50,0,2*Math.PI);
                ctx.stroke();
                ctx.beginPath();
                ctx.arc(100,100,70,0,2*Math.PI);
                ctx.stroke();

                radialGradient = ctx.createRadialGradient(250,50,10,250,50,100);
                radialGradient.addColorStop(0, "red");
                radialGradient.addColorStop(1, "#00f");
                ctx.fillStyle = radialGradient;
                ctx.fillRect(200,0,100,100);

                ctx.beginPath();
                ctx.arc(250,50,10,0,2*Math.PI);
                ctx.stroke();
                ctx.beginPath();
                ctx.arc(250,50,100,0,2*Math.PI);
                ctx.stroke();

                radialGradient = ctx.createRadialGradient(250,150,100,250,150,10);
                radialGradient.addColorStop(0, "red");
                radialGradient.addColorStop(1, "#00f");
                ctx.fillStyle = radialGradient;
                ctx.fillRect(200,100,100,100);

                ctx.beginPath();
                ctx.arc(250,150,100,0,2*Math.PI);
                ctx.stroke();
                ctx.beginPath();
                ctx.arc(250,150,10,0,2*Math.PI);
                ctx.stroke();
            }
        </script>
    </head>
    <body>
        <button type="button" onclick="drawLinearGradient()">drawLinearGradient</button>
        <div>
            <img id="grass" src="grass.jpg"/>
            <button type="button" onclick="drawPattern('repeat')">drawPattern repeat</button>
            <button type="button" onclick="drawPattern('repeat-x')">drawPattern repeat-x</button>
            <button type="button" onclick="drawPattern('repeat-y')">drawPattern repeat-y</button>
            <button type="button" onclick="drawPattern('no-repeat')">drawPattern no-repeat</button>
        </div>
        <div><button type="button" onclick="drawRadialGradient()">drawRadialGradient</button></div>
        <canvas id="canvas" width="400" height="400" style="border:1px solid #aaa">
            <p>Your browser does not support the canvas element!</p>  
        </canvas>
    </body>
</html>

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

阴影

  • shadowColor
    设置或返回用于阴影的颜色。
  • shadowBlur
    设置或返回用于阴影的模糊级别。
  • shadowOffsetX
    设置或返回阴影与形状的水平距离,右为正方向。
  • shadowOffsetY
    设置或返回阴影与形状的垂直距离,下为正方向。
<html>
    <body>
        <canvas id="canvas" width="280" height="400" style="border:1px solid #aaa">
            <p>Your browser does not support the canvas element!</p>  
        </canvas>
        <script type="text/javascript">
            var canvas = document.getElementById('canvas');
            var ctx = canvas.getContext('2d');
            ctx.shadowBlur=0;
            ctx.shadowColor="black";
            ctx.fillStyle='#f00';
            ctx.strokeStyle="#0f0"

            ctx.fillRect(10,10,100,50);
            ctx.strokeRect(130,10,100,50);

            ctx.shadowBlur=20;
            ctx.fillRect(10,100,100,50);
            ctx.strokeRect(130,100,100,50);

            ctx.shadowOffsetX=20;
            ctx.shadowOffsetY=20;
            ctx.fillRect(10,200,100,50);
            ctx.strokeRect(130,200,100,50);

            ctx.shadowBlur=0;
            ctx.fillRect(10,300,100,50);
            ctx.strokeRect(130,300,100,50);
        </script>
    </body>
</html>

这里写图片描述

线条样式

  • lineWidth(default 1)
    设置或返回当前线条的宽度。
  • lineCap
    设置或返回线条的结束端点的样式。
    • butt
      默认。向线条的每个末端为平直的边缘。
    • round
      向线条的每个末端添加圆形线帽。
    • square
      向线条的每个末端添加正方形线帽。
  • lineJoin
    设置或返回折线拐角类型。
    • miter
      默认。创建尖角。
    • bevel
      创建斜角
    • round
      创建圆角
  • miterLimit(default 10)
    设置或返回最大斜接长度。斜接长度指的是在两条线交汇处内角和外角之间的距离。边角的角度越小,斜接长度就会越大。为了避免斜接长度过长,我们才使用 miterLimit 属性。如果斜接长度超过 miterLimit 的值,边角会以 lineJoin 的 “bevel” 类型来显示。如果斜接长度没有超过miterLimit值,那么就会显示为实际的斜切长度。
    只有当 lineJoin 属性为 “miter” 时,miterLimit 才有效。
    这里写图片描述
<html>
    <head>
        <script type="text/javascript">
            function strokeLine(ctx, x1, y1, x2, y2, lineWidth) {
                ctx.strokeStyle="red";
                if(lineWidth === undefined) {
                    ctx.lineWidth = 1;
                } else {
                    ctx.lineWidth = lineWidth;
                }
                ctx.beginPath();
                ctx.moveTo(x1, y1);
                ctx.lineTo(x2, y2);
                //line只有stroke,如果换成fill是画不出线条的,因为没有闭合图形
                ctx.stroke();
            }
            function strokeLineWithCap(ctx, x1, y1, x2, y2, lineCap) {
                ctx.strokeStyle="black";
                ctx.lineWidth = 10;
                ctx.lineCap = lineCap;
                ctx.beginPath();
                ctx.moveTo(x1, y1);
                ctx.lineTo(x2, y2);
                ctx.stroke();
                strokeLine(ctx, x1-20, y1, x2+20, y2);
            }
            function strokeLineJoin(ctx, x1, y1, x2, y2, x3, y3, lineJoin) {
                ctx.strokeStyle="black";
                ctx.lineWidth = 10;
                ctx.lineJoin = lineJoin;
                ctx.beginPath();
                ctx.moveTo(x1, y1);
                ctx.lineTo(x2, y2);
                ctx.lineTo(x3, y3);
                ctx.stroke();
            }
            function draw() {
                var c = document.getElementById("canvas");
                var ctx = c.getContext("2d");
                var x=20,y=20,span=20;
                strokeLineWithCap(ctx, x, y, x+200, y, undefined);
                y+=span;
                strokeLineWithCap(ctx, x, y, x+200, y, "butt");
                y+=span;
                strokeLineWithCap(ctx, x, y, x+200, y, "round");
                y+=span;
                strokeLineWithCap(ctx, x, y, x+200, y, "square");

                x=20,y=100,span=60;
                strokeLineJoin(ctx, x, y, x+100, y+20, x, y+40, "bevel");
                y+=span;
                strokeLineJoin(ctx, x, y, x+100, y+20, x, y+40, "round");
                y+=span;
                strokeLineJoin(ctx, x, y, x+100, y+20, x, y+40, "miter");
                y+=span;
                ctx.miterLimit = 0;
                strokeLineJoin(ctx, x, y, x+100, y+20, x, y+40, "miter");
                y+=span;
                ctx.miterLimit = 1;
                strokeLineJoin(ctx, x, y, x+100, y+20, x, y+40, "miter");
                y+=span;
                ctx.miterLimit = 10;
                strokeLineJoin(ctx, x, y, x+100, y+20, x, y+40, "miter");
                y+=span;
                ctx.miterLimit = 30;
                strokeLineJoin(ctx, x, y, x+100, y+20, x, y+40, "miter");

                x = 90,y=100;
                strokeLine(ctx, x, y, x, y+400);

                x+=30;
                strokeLine(ctx, x, y, x, y+400);

                x+=23;
                strokeLine(ctx, x, y, x, y+400);


                x=200,y=130;
                var lineWidth = 40;
                strokeLine(ctx, x, y, x+100, y, lineWidth);
                ctx.strokeStyle = "blue";
                ctx.lineWidth = 1;
                ctx.beginPath();
                ctx.arc(x,y,lineWidth/2,0,2*Math.PI);
                ctx.stroke();
                ctx.beginPath();
                ctx.arc(x+100,y,lineWidth/2,0,2*Math.PI);
                ctx.stroke();

            }
        </script>
    </head>
    <body onload="draw()">
        <canvas id="canvas" width="400" height="550" style="border:1px solid #aaa">
            <p>Your browser does not support the canvas element!</p>  
        </canvas>
    </body>
</html>

这里写图片描述

矩形

  • rect(x, y, width, height)
    创建矩形。接着使用 stroke() 或 fill() 方法才会在画布上实际地绘制出矩形。
  • fillRect(x, y, width, height)
    绘制“被填充”的矩形
  • strokeRect(x, y, width, height)
    绘制矩形边框
  • clearRect(x, y, width, height)
    清除给定的矩形区域内的像素
<html>
    <body>
         <canvas id="canvas" width="350" height="200" style="border:1px solid #aaa">
            <p>Your browser does not support the canvas element!</p>  
        </canvas>
        <script type="text/javascript">
            var c=document.getElementById("canvas");
            var ctx=c.getContext("2d");

            ctx.beginPath();
            ctx.lineWidth="6";
            ctx.strokeStyle="red";
            ctx.rect(5,5,290,140);
            ctx.stroke();

            ctx.lineWidth="4";
            ctx.strokeStyle="green";
            ctx.strokeRect(30,30,50,50);

            ctx.fillStyle="blue";
            ctx.fillRect(50,50,150,80);

            ctx.clearRect(70,70,40,40);
        </script>
    </body>
</html>

这里写图片描述

路径

  • fill()
    填充当前首尾相连的路径。注意:两个相反方向的路径内部为填充范围。否则最外层路径内部全是填充范围。
  • stroke()
    绘制当前定义的路径。
  • beginPath()
    起始一条路径,或重置当前路径。
  • moveTo()
    把路径移动到画布中的指定点,不创建线条。
  • closePath()
    创建从当前点回到起始点的路径。
  • lineTo()
    创建一个从当前点到该点的路径。
  • clip()
    从原始画布中将当前路径首尾相连并剪裁出来,一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内(不能访问画布上的其他区域)。可以在使用 clip() 方法前通过 save() 方法对当前画布区域进行保存,并在以后的任意时间通过 restore() 方法对其进行恢复。
  • quadraticCurveTo(cpx, cpy, x, y)
    绘制二次贝塞尔曲线。
    • cpx
      贝塞尔控制点的 x 坐标
    • cpy
      贝塞尔控制点的 y 坐标
    • x
      结束点的 x 坐标
    • y
      结束点的 y 坐标
  • bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
    绘制三次贝塞尔曲线。
    • cp1x
      第一个贝塞尔控制点的 x 坐标
    • cp1y
      第一个贝塞尔控制点的 y 坐标
    • cp2x
      第二个贝塞尔控制点的 x 坐标
    • cp2y
      第二个贝塞尔控制点的 y 坐标
    • x
      结束点的 x 坐标
    • y
      结束点的 y 坐标
  • arc(x,y,r,sAngle,eAngle,counterclockwise)
    创建圆或部分圆。顺时针方向为正。
    这里写图片描述
    • x
      圆的中心的 x 坐标。
    • y
      圆的中心的 y 坐标。
    • r
      圆的半径。
    • sAngle
      起始角,以弧度计。(弧的圆形的三点钟位置是 0 度)。
    • eAngle
      结束角,以弧度计。
    • counterclockwise
      可选,规定应该逆时针还是顺时针绘图。False 为顺时针,true 为逆时针。
  • arcTo(arcStartX, arcStartY, arcEndX, arcEndY, r)
    创建两切线之间的弧/曲线。之前一定要使用moveTo() 到某个点,该点若不是弧的起始点则会自动连接到弧的起始点上。
  • isPointInPath()
    如果指定的点位于当前路径内或路径上,则返回 true,否则返回 false。
<html>
    <head>
        <meta charset="UTF-8" />
    </head>
    <body>
        <canvas id="canvas" width="700px" height="450px" style="border:dashed black 1px;">
            <p>Your browser does not support the canvas element!</p>  
        </canvas>
        <script type="text/javascript">
            var c=document.getElementById("canvas");
            var ctx=c.getContext("2d");
            function fillArc(ctx,x,y,color) {
                if(color) {
                    ctx.fillStyle=color;
                } else {
                    ctx.fillStyle="red";
                }
                ctx.beginPath();
                ctx.arc(x,y,3,0,2*Math.PI);
                ctx.fill();
            }

            ctx.beginPath();
            ctx.moveTo(20,20);
            //arcTo之前一定要有moveTo
            ctx.arcTo(100,20,100,70,50);
            ctx.stroke(); 

            fillArc(ctx,50,20);
            fillArc(ctx,100,20);
            fillArc(ctx,100,70);
            fillArc(ctx,100,120);

            ctx.beginPath();
            ctx.arc(200,70,50,0,1.5*Math.PI);
            ctx.stroke();

            ctx.beginPath();
            ctx.arc(300,70,50,0,0.5*Math.PI);
            ctx.stroke();

            ctx.beginPath();
            ctx.arc(200,200,50,0,1.5*Math.PI);
            ctx.fill();

            ctx.beginPath();
            ctx.arc(300,200,50,0,0.5*Math.PI);
            ctx.fill();

            ctx.beginPath();
            ctx.moveTo(400,50);
            ctx.lineTo(400,100);
            ctx.lineTo(450,100);
            ctx.stroke();

            ctx.beginPath();
            ctx.moveTo(400,150);
            ctx.lineTo(400,200);
            ctx.lineTo(450,200);
            //closePath的作用是使路径首尾相连
            ctx.closePath();
            ctx.stroke();

            //isPointInPath
            function checkIsInPath(ctx,x,y) {
                //该函数由于只能判断当前路径,因此不能马上就绘制。凡是在可绘制区域包括边界的都算在路径范围内
                if(ctx.isPointInPath(x,y)) {
                    return true;
                } 
                return false;
            }
            ctx.beginPath();
            ctx.moveTo(400,250);
            ctx.lineTo(400,300);
            ctx.lineTo(450,300);
            ctx.fill();

            var xArr=new Array(400,400,450,425,415,450);
            var yArr=new Array(250,300,300,275,285,250);
            var isInPathArr=new Array();
            for(var i=0;i<xArr.length;i++) {
                isInPathArr.push(checkIsInPath(ctx,xArr[i],yArr[i]));
            }
            var r=3;
            for(var i=0;i<xArr.length;i++) {
                if(isInPathArr[i]) {
                    ctx.fillStyle="green";
                } else {
                    ctx.fillStyle="blue";
                }
                fillArc(ctx,xArr[i],yArr[i],ctx.fillStyle);
            }

            //二次贝塞尔曲线
            var sx=540,sy=50,cx=520,cy=130,ex=650,ey=50;
            ctx.beginPath();
            ctx.moveTo(sx,sy);
            ctx.quadraticCurveTo(cx,cy,ex,ey);
            ctx.stroke();

            fillArc(ctx,sx,sy);
            fillArc(ctx,cx,cy);
            fillArc(ctx,ex,ey);
            ctx.textAlign="center";
            ctx.fillText("开始点("+sx+","+sy+")",sx,sy-10);
            ctx.fillText("结束点("+ex+","+ey+")",ex,ey-10);
            ctx.fillText("控制点("+cx+","+cy+")",cx,cy+20);
            ctx.strokeStyle="orange";
            ctx.beginPath();
            ctx.moveTo(sx,sy);
            ctx.lineTo(cx,cy);
            ctx.lineTo(ex,ey);
            ctx.stroke();

            //三次贝塞尔曲线
            sx=540,sy=200,ex=650,ey=200;
            var c1x=540,c1y=300,c2x=650,c2y=300;
            ctx.strokeStyle="black";
            ctx.beginPath();
            ctx.moveTo(sx,sy);
            ctx.bezierCurveTo(c1x,c1y,c2x,c2y,ex,ey);
            ctx.stroke();

            fillArc(ctx,sx,sy);
            fillArc(ctx,c1x,c1y);
            fillArc(ctx,c2x,c2y);
            fillArc(ctx,ex,ey);
            ctx.fillStyle="blue";
            ctx.fillText("开始点("+sx+","+sy+")",sx,sy-10);
            ctx.fillText("结束点("+ex+","+ey+")",ex,ey-10);
            ctx.fillText("控制点1("+c1x+","+c1y+")",c1x,c1y+20);
            ctx.fillText("控制点2("+c2x+","+c2y+")",c2x,c2y+20);
            ctx.strokeStyle="orange";
            ctx.beginPath();
            ctx.moveTo(sx,sy);
            ctx.lineTo(c1x,c1y);
            ctx.lineTo(c2x,c2y);
            ctx.lineTo(ex,ey);
            ctx.stroke();

            //clip
            ctx.fillStyle="red";
            ctx.fillRect(20,300,150,100);
            ctx.fillStyle="blue";
            ctx.save();
            ctx.beginPath();
            ctx.arc(85,350,50,0,0.75*Math.PI);
            ctx.stroke();

            ctx.clip();
            ctx.fillRect(20,300,150,100);
            ctx.restore();
            ctx.fillRect(220,300,150,100);
        </script>
    </body>
</html> 

这里写图片描述

转换

  • scale(scalewidth, scaleheight)
    缩放当前的坐标系标尺。
  • rotate(angle)
    顺时针旋转画布。angle以弧度计。如需将角度转换为弧度,请使用 degrees*Math.PI/180 公式进行计算。
  • translate(x, y)
    将画布向右移动x, 将画布向下移动y。
  • transform(a, b, c, d, e, f);
    transform() 方法的行为相对于由 rotate(), scale(), translate(), or transform() 组合对画布完成的变换。
    变换矩阵为
    a c e
    b d f
    0 0 1
    • a
      水平缩放
    • b
      水平倾斜
    • c
      垂直倾斜
    • d
      垂直缩放
    • e
      水平移动
    • f
      垂直移动
  • setTransform(a, b, c, d, e, f);
    把当前的变换矩阵重置为单位矩阵,然后以相同的参数运行 transform()。
    变换矩阵为
    a c e
    b d f
    0 0 1
    • a
      水平缩放
    • b
      水平倾斜
    • c
      垂直倾斜
    • d
      垂直缩放
    • e
      水平移动
    • f
      垂直移动
<html>
    <head>
        <style type="text/css">
            canvas {
                 border-width:1px;
                 border-style:dashed;
                 border-color:black;
            }
        </style>
    </head>
    <body>
        <canvas id="canvas1">
            <p>Your browser does not support the canvas element!</p>  
        </canvas>
        <canvas id="canvas2">
            <p>Your browser does not support the canvas element!</p>  
        </canvas>
        <canvas id="canvas3">
            <p>Your browser does not support the canvas element!</p>  
        </canvas>
        <canvas id="canvas4">
            <p>Your browser does not support the canvas element!</p>  
        </canvas>
        <canvas id="canvas5">
            <p>Your browser does not support the canvas element!</p>  
        </canvas>
        <script type="text/javascript">
            function drawGrid(canvas) {
                canvas.width=450;
                canvas.height=450;
                var ctx=c.getContext("2d");
                ctx.lineWidth=1;
                ctx.strokeStyle="black";
                for(var i=0;i<c.width;i+=50) {
                    ctx.beginPath();
                    ctx.moveTo(i,0);
                    ctx.lineTo(i,c.height);
                    ctx.stroke();
                }
                for(var j=0;j<c.height;j+=50) {
                    ctx.beginPath();
                    ctx.moveTo(0,j);
                    ctx.lineTo(c.width,j);
                    ctx.stroke();
                }
            }
        </script>
        <script type="text/javascript">
            //scale
            var c=document.getElementById("canvas1");
            var ctx=c.getContext("2d");
            drawGrid(c);
            ctx.globalAlpha=0.5;
            ctx.save();

            ctx.fillStyle="red";
            ctx.fillRect(0,0,50,50);

            ctx.fillStyle="green";
            ctx.scale(2,2);
            ctx.fillRect(0,0,50,50);

            ctx.fillStyle="blue";
            ctx.scale(2,2);
            ctx.fillRect(0,0,50,50);

            ctx.restore();
            ctx.fillStyle="red";
            ctx.fillRect(50,50,50,50);

            ctx.fillStyle="green";
            ctx.scale(2,2);
            ctx.fillRect(50,50,50,50);

            ctx.fillStyle="blue";
            ctx.scale(2,2);
            ctx.fillRect(50,50,50,50);
        </script>
        <script type="text/javascript">
            //rotate
            var c=document.getElementById("canvas2");
            var ctx=c.getContext("2d");
            drawGrid(c);
            ctx.save();

            ctx.fillStyle="red";
            ctx.fillRect(0,0,50,50);

            ctx.fillStyle="green";
            ctx.rotate(30*Math.PI/180);
            ctx.fillRect(0,0,50,50);

            ctx.fillStyle="blue";
            ctx.rotate(30*Math.PI/180);
            ctx.fillRect(0,0,50,50);

            ctx.restore();
            ctx.fillStyle="red";
            ctx.fillRect(100,0,50,50);

            ctx.fillStyle="green";
            ctx.rotate(30*Math.PI/180);
            ctx.fillRect(100,0,50,50);

            ctx.fillStyle="blue";
            ctx.rotate(30*Math.PI/180);
            ctx.fillRect(100,0,50,50);
        </script>
        <script type="text/javascript">
            //translate
            var c=document.getElementById("canvas3");
            var ctx=c.getContext("2d");
            drawGrid(c);
            ctx.save();

            ctx.fillStyle="red";
            ctx.fillRect(0,0,50,50);

            ctx.fillStyle="green";
            ctx.translate(50,0);
            ctx.fillRect(0,0,50,50);

            ctx.fillStyle="blue";
            ctx.translate(50,0);
            ctx.fillRect(0,0,50,50);

            ctx.restore();
            ctx.fillStyle="red";
            ctx.fillRect(100,100,50,50);

            ctx.fillStyle="green";
            ctx.translate(0,50);
            ctx.fillRect(100,100,50,50);

            ctx.fillStyle="blue";
            ctx.translate(0,50);
            ctx.fillRect(100,100,50,50);
        </script>
        <script type="text/javascript">
            //transform
            var c=document.getElementById("canvas4");
            var ctx=c.getContext("2d");
            drawGrid(c);
            ctx.globalAlpha=0.5;
            ctx.save();

            ctx.fillStyle="red";
            ctx.fillRect(0,0,50,50);

            ctx.transform(1,0.5,0,1,0,0);
            ctx.fillStyle="green";
            ctx.fillRect(0,0,50,50);

            ctx.transform(1,0,1,1,0,0);
            ctx.fillStyle="blue";
            ctx.fillRect(0,0,50,50);

            ctx.restore();
            ctx.fillStyle="red";
            ctx.fillRect(100,100,50,50);

            ctx.transform(1,0.5,0,1,0,0);
            ctx.fillStyle="green";
            ctx.fillRect(100,100,50,50);

            ctx.transform(1,0,1,1,0,0);
            ctx.fillStyle="blue";
            ctx.fillRect(100,100,50,50);
        </script>
        <script type="text/javascript">
            //setTransform
            var c=document.getElementById("canvas5");
            var ctx=c.getContext("2d");
            drawGrid(c);
            ctx.globalAlpha=0.5;

            ctx.fillStyle="red";
            ctx.fillRect(0,0,50,50);

            ctx.setTransform(1,0.5,0,1,0,0);
            ctx.fillStyle="green";
            ctx.fillRect(0,0,50,50);

            ctx.setTransform(1,0,1,1,0,0);
            ctx.fillStyle="blue";
            ctx.fillRect(0,0,50,50);

            //把当前的变换矩阵重置为单位矩阵
            ctx.setTransform(1,0,0,1,0,0);
            ctx.fillStyle="red";
            ctx.fillRect(100,100,50,50);

            ctx.setTransform(1,0.5,0,1,0,0);
            ctx.fillStyle="green";
            ctx.fillRect(100,100,50,50);

            ctx.setTransform(1,0,1,1,0,0);
            ctx.fillStyle="blue";
            ctx.fillRect(100,100,50,50);
        </script>
    </body>
</html>  

这里写图片描述

文本

  • font
    设置或返回文本内容的当前字体属性。该属性的设置方式和CSS中是一样的(参考 http://blog.csdn.net/chy555chy/article/details/53541662
  • textAlign(default start)
    设置或返回文本内容的当前对齐方式。
    • start
      默认。文本在指定的位置开始。(与left效果一样)
    • center
      文本的中心被放置在指定的位置。
    • end
      文本在指定的位置结束。(与right效果一样)
    • left
      文本左对齐到指定位置。(与start效果一样)
    • right
      文本右对齐到指定位置。(与end效果一样)
  • textBaseline(default alphabetic)
    设置或返回在绘制文本时使用的当前文本基线
    • alphabetic
      默认。文本基线是普通的字母的基线。(字母a的底部)
    • bottom
      文本基线是 em 方框的底端。(字母g的底部,和ideographic一样)
    • handing
      文本基线是悬挂基线。(字母h的顶部)
    • ideographic
      文本基线是表意基线。(字母g的底部,和bottom一样)
    • middle
      文本基线是 em 方框的正中。(字母e的横向处)
    • top
      文本基线是 em 方框的顶端。(字母h的顶部都碰不到基线)
  • fillText(text, x, y [, maxWidth])
    在画布上绘制“被填充的”文本。
    • text
      规定在画布上输出的文本。注意:该方法不支持换行符,换行符会被解析为空格。因此如果需要换行,唯一的办法就是指定它的maxWidth。
    • x
      开始绘制文本的 x 坐标位置(相对于画布)。
    • y
      开始绘制文本的 y 坐标位置(相对于画布)。
    • maxWidth
      可选参数。表示允许文本的最大宽度,如果超过该宽度的话,文本会被压缩。
  • strokeText(text, x, y [, maxWidth])
    在画布上绘制文本边框。maxwidth 表示了该字符串的最大宽度,无论字符串有多长,都将限制在该宽度内。
  • measureText(txt).width
    返回指定文本实际绘制的宽度。注意:只包含宽度width属性,不包含高度height属性
<html>
    <<meta charset="UTF-8" />
    <body>
         <canvas id="canvas" width="600" height="550" style="border:1px solid #aaa">
            <p>Your browser does not support the canvas element!</p>  
        </canvas>
        <script type="text/javascript">
            var c = document.getElementById("canvas");
            var ctx = c.getContext("2d");
            ctx.strokeStyle = "blue";
            ctx.font="20px Arial";

            //textAlign
            var x=150,y=20,span=20;
            ctx.moveTo(x,y);
            ctx.lineTo(x,y+110);
            ctx.stroke();

            y+=span;
            ctx.textAlign="center";
            ctx.fillText("textAlign=center",x,y);
            y+=span;
            ctx.textAlign="end";
            ctx.fillText("textAlign=end",x,y);
            y+=span;
            ctx.textAlign="left";
            ctx.fillText("textAlign=left",x,y);
            y+=span;
            ctx.textAlign="right";
            ctx.fillText("textAlign=right",x,y);
            y+=span;
            ctx.textAlign="start";
            ctx.fillText("textAlign=start",x,y);

            ctx.textAlign="start";
            //textBaseline
            x=5,y=170,span=100;
            ctx.moveTo(x,y);
            ctx.lineTo(x+600,y);
            ctx.stroke();

            ctx.textBaseline="alphabetic";          
            ctx.fillText("alphabetic",x,y);
            x+=span;
            ctx.textBaseline="bottom";
            ctx.fillText("bottom g",x,y);
            x+=span;
            ctx.textBaseline="hanging";
            ctx.fillText("hanging",x,y);
            x+=span;
            ctx.textBaseline="ideographic";
            ctx.fillText("ideographic",x,y);
            x+=span;
            ctx.textBaseline="middle";
            ctx.fillText("middle",x,y);
            x+=span;
            ctx.textBaseline="top";
            ctx.fillText("top h",x,y);

            x=20,y=200,span=40;
            textBaseline="alphabetic";
            ctx.font="bold 30px Georgia";
            ctx.fillStyle = "blue";
            ctx.fillText("测试文本",x,y);
            y+=span;
            ctx.strokeText("测试文本",x,y);
            y+=span;
            ctx.fillText("测试文本",x,y,50);
            y+=span;
            ctx.strokeText("测试文本",x,y,50);

            var txt="w3school.com.cn";
            var gradient=ctx.createLinearGradient(x,y,x+ctx.measureText(txt).width,y);
            gradient.addColorStop("0","magenta");
            gradient.addColorStop("0.5","blue");
            gradient.addColorStop("1.0","red");
            ctx.fillStyle=gradient;
            y+=span;
            ctx.fillText(txt,x,y);
            ctx.strokeStyle=gradient;
            y+=span;
            ctx.strokeText(txt,x,y);
            y+=span;
            ctx.fillText(txt,x,y,150);
            y+=span;
            ctx.strokeText(txt,x,y,150);
        </script>
    </body>
</html>

这里写图片描述

绘制图像

  • drawImage(img, x, y)
    向画布上(x, y)点绘制图像、画布或视频。
  • drawImage(img, x, y, width, height)
    在画布上(x, y)点绘制图像,把图像的所有内容绘制到宽度和高度分别为width和height的矩形中。
  • drawImage(img, sx, sy, swidth, sheight, x, y, width, height)
    从图像的(sx, sy)点开始剪裁出一个大小为(swidth, sheight)的矩形,在画布上(x, y)点绘制图像,绘制宽度和高度分别为width和height。
<html>
    <body>
        <style type="text/css">
        </style>
        <img id="img" src="simayi.jpg" />
        <canvas id="canvas1" width="350" height="300" style="border:1px solid #aaa">
            <p>Your browser does not support the canvas element!</p>  
        </canvas>
        <canvas id="canvas2" width="280" height="300" style="border:1px solid #aaa;display:none"/>
        <script type="text/javascript">
            var canvas2 = document.getElementById('canvas2');
            var ctx2 = canvas2.getContext('2d');
            ctx2.fillStyle="red";
            ctx2.fillRect(0, 0, 260, 50);

            var canvas1 = document.getElementById('canvas1');
            var ctx1 = canvas1.getContext('2d');
            var img = document.getElementById('img');
            img.onload = function() {
                ctx1.drawImage(img, 10, 10);
                ctx1.drawImage(img, 290, 10, 50, 50);
            }
            ctx1.drawImage(canvas2, 10, 220);
        </script>
    </body>
</html>

这里写图片描述

像素操作

  • imageData.width
    返回 ImageData 对象的宽度
  • imageData.height
    返回 ImageData 对象的高度
  • imageData.data
    返回一个对象,其包含指定的 ImageData 对象的图像数据,data数据中的像素点从左上角到右下角,且每个像素都存在着四方面的信息,即 RGBA 值。color/alpha 以数组形式存在,并存储于 ImageData 对象的 data 属性中。
    • R - 红色 (0-255)
    • G - 绿色 (0-255)
    • B - 蓝色 (0-255)
    • A - alpha 通道 (0-255; 0 是透明的,255 是完全可见的)
  • createImageData(width,height)
    创建新的、空白的 ImageData 对象。
  • createImageData(imageData)
    创建与指定的另一个 ImageData 对象尺寸相同的新的空的 ImageData 对象(不会复制图像数据)
  • getImageData(x, y, width, height)
    返回 ImageData 对象,该对象为画布上指定的矩形复制像素数据。
  • putImageData(imageData, x, y[, dirtyX, dirtyY, dirtyWidth, dirtyHeight])
    把图像数据(从指定的 ImageData 对象)放回画布上。
    • imageData
      规定要放回画布的 ImageData 对象。
    • x
      ImageData 对象相对画布的左上角的 x 坐标。
    • y
      ImageData 对象相对画布的左上角的 y 坐标。
    • dirtyX
      可选。要在画布上绘制的相对本图像的 x 坐标。
    • dirtyY
      可选。要在画布上绘制的相对本图像的 y 坐标。
    • dirtyWidth
      可选。要在画布上绘制的相对本图像的实际宽度。
    • dirtyHeight
      可选。要在画布上绘制的相对本图像的实际高度。
<html>
    <body>
         <canvas id="canvas" width="250" height="250" style="border:1px solid #aaa">
            <p>Your browser does not support the canvas element!</p>  
        </canvas>
        <script type="text/javascript">
            var c = document.getElementById("canvas");
            var ctx = c.getContext("2d");
            var imgData = ctx.createImageData(200, 200);
            for(var i=0;i<imgData.data.length;i+=4) {
                imgData.data[i]=255;
                imgData.data[i+1]=0;
                imgData.data[i+2]=0;
                imgData.data[i+3]=255;
            }
            ctx.putImageData(imgData,10,10);
            document.write("("+imgData.width+" * "+imgData.height+")");

            imgData = ctx.getImageData(30,30,80,80);
            for(var i=0,j=0,k=0;i<imgData.data.length;i+=4) {
                imgData.data[i]=(j==0?255:0);
                imgData.data[i+1]=(j==1?255:0);
                imgData.data[i+2]=(j==2?255:0);
                imgData.data[i+3]=128;
                k++;
                if(k>25) {
                    k=0;
                    j++;
                    j%=3;
                }
            }
            ctx.putImageData(imgData,30,30);

            imgData = ctx.createImageData(imgData);
            ctx.putImageData(imgData,150,30);

            for(var i=0,j=0,k=0;i<imgData.data.length;i+=4) {
                imgData.data[i]=(j==0?255:0);
                imgData.data[i+1]=(j==1?255:0);
                imgData.data[i+2]=(j==2?255:0);
                imgData.data[i+3]=128;
                k++;
                if(k>40) {
                    k=0;
                    j++;
                    j%=3;
                }
            }
            ctx.putImageData(imgData,30,120);

            ctx.lineWidth=2;
            ctx.strokeStyle="black";
            ctx.strokeRect(140,120,80,80);
            ctx.putImageData(imgData,140,120, 20,20,60,60);
        </script>
    </body>
</html>

这里写图片描述

合成

  • globalAlpha
    设置或返回绘图的当前 alpha 或透明值
  • globalCompositeOperation
    设置或返回新图像如何绘制到已有的图像上
    • source-over
      默认。在目标图像上显示源图像。
    • source-atop
      在目标图像顶部显示源图像。源图像位于目标图像之外的部分是不可见的。
    • source-in
      在目标图像中显示源图像。只有目标图像内的源图像部分会显示,目标图像是透明的。
    • source-out
      在目标图像之外显示源图像。只会显示目标图像之外源图像部分,目标图像是透明的。
    • destination-over
      在源图像上方显示目标图像。
    • destination-atop
      在源图像顶部显示目标图像。源图像之外的目标图像部分不会被显示。
    • destination-in
      在源图像中显示目标图像。只有源图像内的目标图像部分会被显示,源图像是透明的。
    • destination-out
      在源图像外显示目标图像。只有源图像外的目标图像部分会被显示,源图像是透明的。
    • lighter
      显示源图像 + 目标图像,即RGB各分量相加。
    • copy
      显示源图像。忽略目标图像。
    • xor
      使用异或操作对源图像与目标图像进行组合。
<html>
    <body>
        <canvas id="canvas" width="1000" height="500" style="border:1px solid #aaa">
            <p>Your browser does not support the canvas element!</p>  
        </canvas>
        <script type="text/javascript">
            var c = document.getElementById("canvas");
            var ctx = c.getContext("2d");

            var x=20,y=20;
            ctx.fillStyle="red";
            ctx.fillRect(x,y,70,50);

            x+=30,y+=30;
            ctx.globalAlpha=0.2;
            ctx.fillStyle="blue";
            ctx.fillRect(x,y,70,50);

            x+=30,y+=30;
            ctx.fillStyle="green";
            ctx.fillRect(x,y,70,50);

            ctx.globalAlpha=1;
            ctx.font="14px Arial";
            ctx.fillStyle="black";
            ctx.fillText("globalAlpha",20,150);

            function testGlobalCompositeOperation(x,y,compositeOperation) {
                var c2 = document.createElement("canvas");
                c2.width=120;
                c2.height=130;
                var ctx2 = c2.getContext("2d");

                ctx2.fillStyle="red";
                ctx2.fillRect(10,10,70,50);
                ctx2.globalCompositeOperation=compositeOperation;
                ctx2.fillStyle="blue";
                ctx2.fillRect(30,30,70,50);

                <!-- 由于该属性会作用到drawImage上导致有些图像消失,所以用完之后得恢复默认属性(不能设置为undefined) -->
                ctx2.globalCompositeOperation = "source-over";
                ctx2.font="14px Arial";
                ctx2.fillStyle="black";
                ctx2.fillText(compositeOperation,10,120);

                ctx.drawImage(c2, x, y, c2.width, c2.height);
                ctx.strokeRect(x, y, c2.width, c2.height);
            }

            var gco=new Array();
            gco.push("source-atop");
            gco.push("source-in");
            gco.push("source-out");
            gco.push("source-over");
            gco.push("destination-atop");
            gco.push("destination-in");
            gco.push("destination-out");
            gco.push("destination-over");
            gco.push("lighter");
            gco.push("copy");
            gco.push("xor");

            x=20,y=180;
            var span=160;

            for (var i=0;i<gco.length;i++) {
                testGlobalCompositeOperation(x,y,gco[i]);
                if(i==5) { 
                    x=20,y+=150;
                } else {
                    x+=span;
                }
            }

            ctx.fillText("globalCompositeOperation", 20, 490);
        </script>
    </body>
</html>

这里写图片描述

其它

save() 和 restore()

Canvas 的状态是以堆(stack)的方式保存的,每一次调用 save 方法,当前的状态就会被推入堆中保存起来。

这种状态包括:当前应用的变形(即移动,旋转和缩放等): strokeStyle, fillStyle, globalAlpha, lineWidth, lineCap, lineJoin, miterLimit, shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor, globalCompositeOperation 的值。

你可以调用任意多次 save 方法。每一次调用 restore 方法,上一个保存的状态就从堆中弹出,所有设定都恢复。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值