简介

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之前一定要有moveToctx.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();//isPointInPathfunction 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();//clipctx.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">//scalevar 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">//rotatevar 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">//translatevar 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">//transformvar 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">//setTransformvar 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";//textAlignvar 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";//textBaselinex=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 方法,上一个保存的状态就从堆中弹出,所有设定都恢复。

JavaScript canvas相关推荐

  1. 如何用 JavaScript+Canvas 开发一款超级烧脑小游戏?

    作者 | huangjianke 责编 | 伍杏玲 出品 | CSDN(ID:CSDNnews) [CSDN 编者按]据微信最新数据,微信小游戏累计注册用户量已突破10亿.那么初学者如何开发一款好玩又 ...

  2. html鼠标拖尾效果,javascript canvas拖尾效果

    {$title} var lujinglist = []; //制作路径 for (var x = 10; x <= 300; x++) { var dian = [x, 50]; lujing ...

  3. JavaScript+ Canvas开发趣味小游戏《贪吃蛇》

    一.效果展示 二.<贪吃蛇>基本实现思路 蛇头部分+蛇身体部分:采用对象形式来存储坐标,并将每个坐标对象放到一个snake数组中,方便使用.设置每个方格宽度30px,高度30px,画布高度 ...

  4. JavaScript canvas实现俄罗斯方块

    俄罗斯方块是个很经典的小游戏,也尝试写了一下.不过我想用尽量简洁逻辑清晰的代码实现.不用过多的代码记录下落方块的模型,或者记录每一个下落方块的x,y.想了下面的思路,然后发现这样很写很简明. 俄罗斯方 ...

  5. JavaScript - canvas - 画直角坐标系

    文章目录 预备知识 关于 canvas 画布的原点 画直线 项目结构 HTML CSS JavaScript 效果 设置 canvas 起点偏移(平移变换) JavaScript 效果 画空心三角形 ...

  6. JavaScript - canvas - 镜像图片

    文章目录 参考 <!DOCTYPE html> <html><head><meta charset="utf-8"><titl ...

  7. JavaScript +canvas简易画板的实现

    本篇文章讲的是利用的canvas的一些属性制作一个简易的画板,由于本人的时间不足,以及能力也有限,所以功能比较简单,喜欢自己学习的同学有兴趣话可以自己加上一些功能.直接上代码了. <!DOCTY ...

  8. [JavaScript] canvas 合成图片和文字

    Canvas Canvas 是 HTML5 新增的组件,就像一个画板,用 js 这杆笔,在上面乱涂乱画 创建一个 canvas <canvas id="stockGraph" ...

  9. javascript canvas九宫格小程序

    js核心代码 1 /* 2 *canvasid:html canvas标签id 3 *imageid:html img 标签id 4 *gridcountX:x轴图片分割个数 5 *gridcount ...

最新文章

  1. Javascript 将时间戳显示为“多久前”
  2. 为何python不好找工作k-给急着找工作的人一些建议,别在被骗了!
  3. Elasticsearch查询相关总结以及timestamp和时区问题
  4. “穿透”与“征兆”:长篇小说《环形女人》(一)
  5. 关于企业应用SAP成本管理模式与方法的一些思考
  6. C# 性能优化之斤斤计较篇 一
  7. java4选择结构 二
  8. 技术干货 | SDN controller高可用之路
  9. WebService学习总结(一)——WebService的相关概念
  10. 删除用户账户|win7系统怎么删除用户账户
  11. 阿里、腾讯、知乎裁员 那些被裁的程序员怎么办?
  12. Oracle-opatchauto自动安装补丁失败导致RAC集群异常问题
  13. 国外计算机科学的 lab,真滴牛逼!
  14. cp: omitting directory xxx
  15. cubase怎么添加midi设备_在 Cubase 中设置 MIDI 键盘的走带控制器和旋钮推子等控制器...
  16. python标准库math中sin函数的参数单位是角度吗_弧度 - math.h中的三角函数,参数是弧度,不是角度...
  17. C++ decorator(装饰)模式
  18. Win11共享文件夹打不开怎么办
  19. NGS项目四:高通量测序在植物生物胁迫研究中的应用
  20. 乌班图linux分辨率不能调,ubuntu分辨率1024*768无法选择解决方法

热门文章

  1. kafka-topics.sh java.rmi.server.ExportException: Port already in use: 5555
  2. 结算系统业务监控实践
  3. C# PDF转为图片的方法
  4. 企业,绩效管理为何力不从心
  5. 水清冷冷:Photoshop CC2020/ PSCC2020 安装图文教程及学习
  6. 微信公众号自定义菜单失效,无法设置的解决方法
  7. 在Centos7中配置NIS的详细过程
  8. Java提取URL某个参数的值
  9. android chrome72,Chrome 72正式版发布
  10. [附源码]java毕业设计小说网站的设计与实现1