💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
[TOC] ## 状态 Canvas 是基于 “状态” 来绘制图形的。每一次绘制(stroke() 或者 fill()),Canvas 都会检测整个程序定义的所有状态,一个绘画的状态包括: * 当前应用的变形(即移动,旋转和缩放) * `strokeStyle`,`fillStyle`,`globalAlpha`,`lineWidth`,`lineCap`,`lineJoin`,`miterLimit`,`shadowOffsetX`,`shadowOffsetY`,`shadowBlur`,`shadowColor`,`globalCompositeOperation` 的值 * 当前的裁切路径(`clipping path`) Canvas 提供了两个操作状态的方法:save() 和 restore() 我们可以认为 Canvas 的状态存储在一个栈中,每当 save() 方法被调用,当前状态就被推入状态栈中,可以调用任意多次 save() 方法。而 restore() 方法就相当于弹出状态栈的栈顶状态并恢复到这个状态。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>canvas</title> </head> <body> <canvas id="canvas" width="500" height="200" style="border: 1px solid gray; display: block; margin: 0 auto"></canvas> <script> window.onload = function(){ let cnv = document.getElementById('canvas') let cxt = cnv.getContext('2d') // cxt.save() cxt.fillStyle = 'HotPink' cxt.translate(30, 30) cxt.fillRect(0, 0, 100, 50) // cxt.restore() cxt.fillStyle = 'LightSkyBlue' cxt.translate(60, 60) cxt.fillRect(0, 0, 100, 50) } </script> </body> </html> ``` ![](https://img.kancloud.cn/fa/f4/faf410b99607a403f24c53f4a7e899d1_681x276.png) 上面这个例子中,如果我们想让第二次 translate() 相对于最初的坐标原点进行移动,就可以利用 save() 和 restore() 方法来实现。 ![](https://img.kancloud.cn/e2/94/e2947aa06103376a5e40f69dc97c2c10_671x271.png) ## 路径 Canvas 提供了三种操作路径的方法 | 方法 | 说明 | | --- | --- | | beginPath() | 开始一条新的路径 | | closePath() | 关闭当前路径 | | isPointPath() | 判断某一个点是否存在于当前路径 | 案例: ```js // 开始路径 context.beginPath(); context.strokeStyle = 'blue'; context.moveTo(60, 20); context.lineTo(220, 20); context.stroke(); // 开始路径 again context.beginPath(); context.strokeStyle = 'green'; context.moveTo(60, 20); context.lineTo(160, 120); context.stroke(); ``` ![](https://img.kancloud.cn/4e/78/4e7801c53e89b749db74337db33bc592_403x204.png =300x) 再看下面的代码: ```js // 开始路径 context.beginPath(); context.strokeStyle = 'blue'; context.moveTo(60, 20); context.lineTo(220, 20); context.stroke(); context.strokeStyle = 'green'; context.moveTo(60, 20); context.lineTo(160, 120); context.stroke(); ``` ![](https://img.kancloud.cn/91/72/9172c1bea7e5add38cde40636d989912_394x204.png =300x) 之前提到过,Canvas 是基于状态来绘制图形的,那么当一个状态值没有被改变时,Canvas 就一直使用最初的值,而当一个状态值被改变时,就要分两种情况考虑: (1) 如果使用 beginPath() 开始一个新的路径,则不同路径使用不同的值,即绘制结果不影响之前的路径。 (2) 如果没有使用 beginPath() 开始一个新的路径,则后面的值会覆盖前面的值。 比如上面的第二张图两条直线属于同一路径,用新的状态来绘制时自然就会影响这两条直线了。 ### closePath() closePath() 方法的作用是连接起点与终点,使其成为一个封闭的图形,即 “关闭路径”。需要注意的是 “关闭路径” 并不等同于 “结束路径”,即其并没有起到新调用一次 beginPath() 的作用。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>canvas</title> </head> <body> <canvas id="canvas" width="500" height="300" style="border: 1px solid gray; display: block; margin: 0 auto"></canvas> <script> window.onload = function(){ let cnv = document.getElementById('canvas') let cxt = cnv.getContext('2d') cxt.beginPath() cxt.strokeStyle = 'red' cxt.arc(70, 70, 50, 0, -90 * Math.PI / 180, true) cxt.closePath() cxt.stroke() // cxt.beginPath() cxt.strokeStyle = 'blue' cxt.arc(70, 120, 50, 0, -90 * Math.PI / 180, true) cxt.closePath() cxt.stroke() } </script> </body> </html> ``` ![](https://img.kancloud.cn/e6/91/e691049a07ce4b12dfa618494cd3924b_654x395.png =300x) 添加了 beginPath() 后才能达到预期的效果。 ![](https://img.kancloud.cn/4c/d2/4cd2dca2ed0567e5f67a0653e3b01bec_653x395.png =300x) ### isPointPath() 方法 ```js cxt.isPointInPath(x, y) ``` 该方法用于判断点(x,y)是否位于当前路径中,如果存在则返回 true,否则返回 false。