Canvas 学习笔记(基础篇) 绘制图形、路径

<canvas>是一个可以使用脚本 (通常为JavaScript) 来绘制图形的 HTML 元素。最早由 Apple 引入 WebKit,用于 Mac OS X 的 Dashboard,随后被各个浏览器实现。如今,所有主流的浏览器都支持它。

Canvas 的默认大小为 300 像素 ×150 像素(宽 × 高,像素的单位是 px)。但是,可以使用 HTML 的高度和宽度属性来自定义 Canvas 的尺寸。
如:<canvas id="tutorial" width="150" height="150"></canvas>

canvas可以在浏览器不支持的情况下,指定替代内容,同时canvas需要闭合标签。
<canvas id="canvas" width="150" height="150">您的浏览器不支持canvas,请升级!</canvas>

渲染上下文:<canvas> 元素创造了一个固定大小的画布,它公开了一个或多个渲染上下文,其可以用来绘制和处理要展示的内容。可以使用getContext方法获取,如:

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

Canvas 基础用法:

<html>
  <head>
    <title>Canvas tutorial</title>
    <script type="text/javascript">
      function draw(){
        var canvas = document.getElementById('tutorial');
        //检查支持性
        if (canvas.getContext){
          var ctx = canvas.getContext('2d'); //渲染上下文
        }
      }
    </script>
    <style type="text/css">
      canvas { border: 1px solid black; }
    </style>
  </head>
  <body onload="draw();">
    <canvas id="tutorial" width="150" height="150"></canvas>
  </body>
</html>

绘制图形

<canvas> 只支持两种形式的图形绘制:矩形和路径(由一系列点连成的线段)。
所有其他类型的图形都是通过一条或者多条路径组合而成的。

矩形绘制(三种方法)
fillRect(x, y, width, height)
绘制一个填充的矩形
strokeRect(x, y, width, height)
绘制一个矩形的边框
clearRect(x, y, width, height)
清除指定矩形区域,让清除部分完全透明。
上面提供的方法之中每一个都包含了相同的参数。x与y指定了在canvas画布上所绘制的矩形的左上角(相对于原点)的坐标。width和height设置矩形的尺寸。

function draw() {
  var canvas = document.getElementById('canvas');
  if (canvas.getContext) {
    var ctx = canvas.getContext('2d');

    ctx.fillRect(25, 25, 100, 100); //默认会用黑色填充
    ctx.clearRect(45, 45, 60, 60); //区域被清除,透明
    ctx.strokeRect(50, 50, 50, 50); //默认边框为黑色
  }
}
image.png

绘制路径

图形的基本元素是路径。路径是通过不同颜色和宽度的线段或曲线相连形成的不同形状的点的集合。一个路径,甚至一个子路径,都是闭合的。使用路径绘制图形需要一些额外的步骤。

1.首先,你需要创建路径起始点。
2.然后你使用画图命令去画出路径。
3.之后你把路径封闭。
4.一旦路径生成,你就能通过描边或填充路径区域来渲染图形。

以下是所要用到的函数:

beginPath()
新建一条路径,生成之后,图形绘制命令被指向到路径上生成路径。
closePath()
闭合路径之后图形绘制命令又重新指向到上下文中。
stroke()
通过线条来绘制图形轮廓。
fill()
通过填充路径的内容区域生成实心的图形。

移动笔触
moveTo(x, y)
将笔触移动到指定的坐标x以及y上。
绘制直线
lineTo(x, y)
绘制一条从当前位置到指定x以及y位置的直线。

生成路径的第一步叫做 beginPath()。本质上,路径是由很多子路径构成,这些子路径都是在一个列表中,所有的子路径(线、弧形、等等)构成图形。而每次这个方法调用之后,列表清空重置,然后我们就可以重新绘制新的图形。
第二步就是调用函数指定绘制路径
第三,就是闭合路径 closePath(),不是必需的。这个方法会通过绘制一条从当前点到开始点的直线来闭合图形。如果图形是已经闭合了的,即当前点为开始点,该函数什么也不做。当你调用 fill() 函数时,所有没有闭合的形状都会自动闭合,所以你不需要调用 closePath() 函数。但是调用 stroke() 时不会自动闭合

//绘制三角形
function draw() {
  var canvas = document.getElementById('canvas');
  if (canvas.getContext){
  var ctx = canvas.getContext('2d');

  // 填充三角形
  ctx.beginPath();
  ctx.moveTo(25, 25);
  ctx.lineTo(105, 25);
  ctx.lineTo(25, 105);
  ctx.fill();

  // 描边三角形
  ctx.beginPath();
  ctx.moveTo(125, 125);
  ctx.lineTo(125, 45);
  ctx.lineTo(45, 125);
  ctx.closePath();
  ctx.stroke();
  }
}
image.png

你会注意到填充与描边三角形步骤有所不同。正如上面所提到的,因为路径使用填充(fill)时,路径自动闭合,使用描边(stroke)则不会闭合路径。如果没有添加闭合路径closePath()到描述三角形函数中,则只绘制了两条线段,并不是一个完整的三角形。

绘制圆弧

arc(x, y, radius, startAngle, endAngle, anticlockwise)
画一个以(x,y)为圆心的以radius为半径的圆弧(圆),从startAngle开始到endAngle结束,按照anticlockwise给定的方向(默认为顺时针)来生成。
arcTo(x1, y1, x2, y2, radius)
根据给定的控制点和半径画一段圆弧,再以直线连接两个控制点。

该方法有六个参数:x,y为绘制圆弧所在圆上的圆心坐标。radius为半径。startAngle以及endAngle参数用弧度定义了开始以及结束的弧度。这些都是以x轴为基准。参数anticlockwise为一个布尔值。为true时,是逆时针方向,否则顺时针方向。
注意:arc()函数中表示角的单位是弧度,不是角度。角度与弧度的js表达式:弧度=(Math.PI/180)*角度
比如:绘制半圆

ctx.arc(100, 100, 50, 0,Math.PI, false)
ctx.stroke()

image.png

二次贝塞曲线及三次贝塞曲线
quadraticCurveTo(cp1x, cp1y, x, y)绘制二次贝塞尔曲线,cp1x,cp1y 为一个控制点,x,y 为结束点。
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) 绘制三次贝塞尔曲线,cp1x,cp1y为控制点一,cp2x,cp2y为控制点二,x,y为结束点。
image.png

比如:

var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(75, 25);
ctx.quadraticCurveTo(25, 25, 25, 62.5);

image.png

使用二次贝塞曲线 绘制圆角矩形

function roundedRect(ctx, x, y, width, height, radius){
  ctx.beginPath();
  ctx.moveTo(x, y + radius); 
  ctx.lineTo(x, y + height - radius); //画左侧竖线线条
  ctx.quadraticCurveTo(x, y + height, x + radius, y + height);//左下角圆角
  ctx.lineTo(x + width - radius, y + height);//下方线条
  ctx.quadraticCurveTo(x + width, y + height, x + width, y + height - radius);//右下角圆角
  ctx.lineTo(x + width, y + radius);//画右侧竖线线条
  ctx.quadraticCurveTo(x + width, y, x + width - radius, y);//画右上圆角
  ctx.lineTo(x + radius, y);//画上方线条
  ctx.quadraticCurveTo(x, y, x, y + radius);//画左上角圆角
  ctx.stroke(); //画线
}

使用样式和颜色

色彩
设置图形的填充颜色 fillStyle = color
设置图形轮廓的颜色 strokeStyle = color
一旦您设置了 strokeStyle 或者 fillStyle 的值,那么这个新值就会成为新绘制的图形的默认值。如果你要给每个图形上不同的颜色,你需要重新设置 fillStyle 或 strokeStyle 的值。
如:ctx.fillStyle = "#FFA500";

透明度
globalAlpha = transparencyValue (这个属性影响到 canvas 里所有图形的透明度,有效的值范围是 0.0(完全透明)到 1.0(完全不透明),默认是 1.0。)
比如:

var ctx = canvas.getContext('2d');
// 画背景(四个矩形背景)
ctx.fillStyle = '#FD0';
ctx.fillRect(0, 0, 75, 75);
ctx.fillStyle = '#6C0';
ctx.fillRect(75, 0, 75, 75);
ctx.fillStyle = '#09F';
ctx.fillRect(0, 75, 75, 75);
ctx.fillStyle = '#F30';
ctx.fillRect(75, 75, 75, 75);
ctx.fillStyle = '#FFF';
// 设置透明度值
ctx.globalAlpha = 0.2;

// 画半透明圆
for (var i = 0; i < 7; i++) {
    ctx.beginPath();
    ctx.arc(75, 75, 10 + 10 * i, 0, Math.PI * 2, true);
    ctx.fill();
}
image.png

线型
可以通过一系列属性设置线的样式
设置线条宽度 lineWidth = value
设置线条末端样式 lineCap = butt,round 和 square。默认是 butt
设定线条与线条间接合处的样式 lineJoin = round, bevel 和 miter。默认是 miter
设置虚线:
setLineDash方法,接受一个数组,来指定线段与间隙的交替,比如:ctx.setLineDash([4, 2]);
lineDashOffset 属性设置起始偏移量
限制当两条线相交时交接处最大长度 :miterLimit = value(没看明白?)

渐变
创建canvasGradient对象
createLinearGradient(x1, y1, x2, y2)接受 4 个参数,表示渐变的起点 (x1,y1) 与终点 (x2,y2)
createRadialGradient(x1, y1, r1, x2, y2, r2) 接受 6 个参数,前三个定义一个以 (x1,y1) 为原点,半径为 r1 的圆,后三个参数则定义另一个以 (x2,y2) 为原点,半径为 r2 的圆。
上色:addColorStop
gradient.addColorStop(position, color) 其中position 参数必须是一个 0.0 与 1.0 之间的数值,表示渐变中颜色所在的相对位置。
比如最简单的:黑白渐变

var ctx = canvas.getContext('2d');
var lineargradient = ctx.createLinearGradient(0, 0, 0, 100);
lineargradient.addColorStop(0, 'white');
lineargradient.addColorStop(1, 'black');
ctx.fillStyle = lineargradient;
ctx.fillRect(20, 20, 200, 100);

image.png

图案样式Patterns
createPattern(image, type):该方法接受两个参数。Image 可以是一个 Image 对象的引用,或者另一个 canvas 对象。Type 必须是下面的字符串值之一:repeat,repeat-x,repeat-y 和 no-repeat。
比如:

function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');

  // 创建新 image 对象,用作图案
  var img = new Image();
  img.src = 'canvas_createpattern.png';
  img.onload = function() {

    // 创建图案
    var ptrn = ctx.createPattern(img, 'repeat');
    ctx.fillStyle = ptrn;
    ctx.fillRect(0, 0, 150, 150);

  }
}

image.png

阴影
X轴偏移:shadowOffsetX = float
Y轴偏移:shadowOffsetY = float
模糊程度:shadowBlur = float
颜色:shadowColor = color

function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');

  ctx.shadowOffsetX = 2;
  ctx.shadowOffsetY = 2;
  ctx.shadowBlur = 2;
  ctx.shadowColor = "rgba(0, 0, 0, 0.5)";

  ctx.font = "20px Times New Roman";
  ctx.fillStyle = "Black";
  ctx.fillText("Sample String", 5, 30);
}

image.png

绘制文本
canvas 提供了两种方法来渲染文本
fillText(text, x, y [, maxWidth]) 在指定的 (x,y) 位置填充指定的文本,绘制的最大宽度是可选的。
strokeText(text, x, y [, maxWidth]) 在指定的 (x,y) 位置绘制文本边框,绘制的最大宽度是可选的。
举例:使用fillText

function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');
  ctx.font = "48px serif";
  ctx.fillText("Hello world", 10, 50);
}
image.png

使用strokeText 文本边框

function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');
  ctx.font = "48px serif";
  ctx.strokeText("Hello world", 10, 50);
}

image.png

设置文本样式
font = value 这个字符串使用和 CSS font 属性相同的语法。默认的字体是 10px sans-serif。
?textAlign = value 文本对齐选项。可选的值包括:start, end, left, right or center. 默认值是 start
textBaseline = value 基线对齐选项。可选的值包括:top, hanging, middle, alphabetic, ideographic, bottom。默认值是 alphabetic。
direction = value 文本方向。可能的值包括:ltr, rtl, inherit。默认值是 inherit。

预测量文本宽度 measureText()将返回一个 TextMetrics对象的宽度、所在像素,这些体现文本特性的属性
比如:

 var ctx = document.getElementById('canvas').getContext('2d');
 var text = ctx.measureText("foo"); // TextMetrics object
 text.width; // 16;

使用图像

绘制图片:drawImage(image, x, y) 其中 image 是 image 或者 canvas 对象,x 和 y 是其在目标 canvas 里的起始坐标。
缩放:drawImage(image, x, y, width, height)
切片:drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
其中 前 4 个是定义图像源的切片位置和大小,后 4 个则是定义切片的目标显示位置和大小。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容