[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。
- 序言 & 更新日志
- H5
- Canvas
- 序言
- Part1-直线、矩形、多边形
- Part2-曲线图形
- Part3-线条操作
- Part4-文本操作
- Part5-图像操作
- Part6-变形操作
- Part7-像素操作
- Part8-渐变与阴影
- Part9-路径与状态
- Part10-物理动画
- Part11-边界检测
- Part12-碰撞检测
- Part13-用户交互
- Part14-高级动画
- CSS
- SCSS
- codePen
- 速查表
- 面试题
- 《CSS Secrets》
- SVG
- 移动端适配
- 滤镜(filter)的使用
- JS
- 基础概念
- 作用域、作用域链、闭包
- this
- 原型与继承
- 数组、字符串、Map、Set方法整理
- 垃圾回收机制
- DOM
- BOM
- 事件循环
- 严格模式
- 正则表达式
- ES6部分
- 设计模式
- AJAX
- 模块化
- 读冴羽博客笔记
- 第一部分总结-深入JS系列
- 第二部分总结-专题系列
- 第三部分总结-ES6系列
- 网络请求中的数据类型
- 事件
- 表单
- 函数式编程
- Tips
- JS-Coding
- Framework
- Vue
- 书写规范
- 基础
- vue-router & vuex
- 深入浅出 Vue
- 响应式原理及其他
- new Vue 发生了什么
- 组件化
- 编译流程
- Vue Router
- Vuex
- 前端路由的简单实现
- React
- 基础
- 书写规范
- Redux & react-router
- immutable.js
- CSS 管理
- React 16新特性-Fiber 与 Hook
- 《深入浅出React和Redux》笔记
- 前半部分
- 后半部分
- react-transition-group
- Vue 与 React 的对比
- 工程化与架构
- Hybird
- React Native
- 新手上路
- 内置组件
- 常用插件
- 问题记录
- Echarts
- 基础
- Electron
- 序言
- 配置 Electron 开发环境 & 基础概念
- React + TypeScript 仿 Antd
- TypeScript 基础
- 样式设计
- 组件测试
- 图标解决方案
- Algorithm
- 排序算法及常见问题
- 剑指 offer
- 动态规划
- DataStruct
- 概述
- 树
- 链表
- Network
- Performance
- Webpack
- PWA
- Browser
- Safety
- 微信小程序
- mpvue 课程实战记录
- 服务器
- 操作系统基础知识
- Linux
- Nginx
- redis
- node.js
- 基础及原生模块
- express框架
- node.js操作数据库
- 《深入浅出 node.js》笔记
- 前半部分
- 后半部分
- 数据库
- SQL
- 面试题收集
- 智力题
- 面试题精选1
- 面试题精选2
- 问答篇
- Other
- markdown 书写
- Git
- LaTex 常用命令