路径与多边形

要在画布上画线或者填充由这些线包围的区域,首先需要定义一个路径。路径是一个或多个子路径序列。
而子路径则是两个或多个通过线段(或曲线段)连接起来的点的序列。
开始新路径要调用 beginPath() 方法,而开始定义子路径要调用 moveTo() 方法。
在通过 moveTo() 建立起子路径的起点后,可以调用 lineTo() 将该点连接到一个新的点。

以下代码定义了一个包含两个线段的路径:

1
2
3
4
c.beginPath()  // 开始一个新路径
c.moveTo(100,100)   // 开始一个子路径,起点为 (100,100)
c.lineTo(200,200) // 用线段连接点 (100,100) 和 (200,200)    
c.lineTo(100,200); // 用线段连接点 (200,200) 和 (100,200)    

这几行代码定义了一个路径,但并没有在画布上绘制任何东西。
要绘制(或"描画")路径中的两条线段,必须调用 stroke() 方法,而要填充这些线段定义的区域,则要调用 fill() 方法:

1
2
c.fill()  // 填充三角形区域      
c.stroke()  // 描画三角形的两条边    
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <title>Page Title</title>
</head>
<body>
  <canvas id="graph" width=300 height=300></canvas>
  <script>
    let canvas = document.querySelector("#graph") // 取得第一个画布元素   
    let c = canvas.getContext("2d")  // 取得 2D 回去上下文   
    c.beginPath()  // 开始一个新路径
    c.moveTo(100,100)   // 开始一个子路径,起点为 (100,100)
    c.lineTo(200,200) // 用线段连接点 (100,100) 和 (200,200)    
    c.lineTo(100,200); // 用线段连接点 (200,200) 和 (100,200)   
    c.fillStyle = '#f00'
    c.fill()   // 填充三角形区域   
    c.stroke()   // 描画三角形的两条边  
  </script>
</body>
</html>

我们注意到,定义的子路径是“开放的”。整个路径只包含两条线段,而且终点并未连接到起点。这意味着图中的三角形区域并不是闭合的区域
fill() 方法在填充开放路径时,就好像有一条直线连接了子路径的终点与起点一样。这也是为什么以上代码填充的是三角形区域,而描画的只有三角形的两条边

如果想描画这个三角形的所有边,必须调用 closePath() 把子路径的终点连接到起点(也可以调用 lineTo(100,100), 但这样做的结果是得到三条共享起点和终点的线段,路径并没有真正闭合。在用宽线画图时,还是使用 closePath() 的视觉效果更好)