【Web技术】1401- 图解 Canvas 入门

发表于 2年以前  | 总阅读数:388 次

在前端领域,如果只是懂 Vue 或者 React ,未来在职场的竞争力可能会比较弱。

根据我多年在家待业经验来看,前端未来在 数据可视化AI 这两个领域会比较香,而 Canvas 是数据可视化在前端方面的基础技术。

本文就用光的速度将 canvas 给入门了。

01.gif

要入门一个技术,前期最重要是快!所以本文只讲入门内容,能应付简单项目。深入的知识点会在其他文章讲解。

Canvas 是什么?

  • Canvas 中文名叫 “画布”,是 HTML5 新增的一个标签。
  • Canvas 允许开发者通过 JS在这个标签上绘制各种图案。
  • Canvas 拥有多种绘制路径、矩形、圆形、字符以及图片的方法。
  • Canvas 在某些情况下可以 “代替” 图片。
  • Canvas 可用于动画、游戏、数据可视化、图片编辑器、实时视频处理等领域。

Canvas 和 SVG 的区别

Canvas SVG
用JS动态生成元素(一个HTML元素) 用XML描述元素(类似HTML元素那样,可用多个元素来描述一个图形)
位图(受屏幕分辨率影响) 矢量图(不受屏幕分辨率影响)
不支持事件 支持事件
数据发生变化需要重绘 不需要重绘

就上面的描述而言可能有点难懂,你可以打开 AntV 旗下的图形编辑引擎做对比。G6[1] 是使用 canvas 开发的,X6[2] 是使用 svg 开发的。

我的建议是:如果要展示的数据量比较大,比如一条数据就是一个元素节点,那使用 canvas 会比较合适;如果用户操作的交互比较多,而且对清晰度有要求(矢量图),那么使用 svg 会比较合适。

起步

学习前端一定要动手敲代码,然后看效果展示。

起步阶段会用几句代码说明 canvas 如何使用,本例会画一条直线。

画条直线

  1. HTML 中创建 canvas 元素
  2. 通过 js 获取 canvas 标签
  3. canvas 标签中获取到绘图工具
  4. 通过绘图工具,在 canvas 标签上绘制图形

02.png

<!-- 1、创建 canvas 元素 -->
<canvas
  id="c"
  width="300"
  height="200"
  style="border: 1px solid #ccc;"
></canvas>

<script>
  // 2、获取 canvas 对象
  const cnv = document.getElementById('c')

  // 3、获取 canvas 上下文环境对象
  const cxt = cnv.getContext('2d')

  // 4、绘制图形
  cxt.moveTo(100, 100) // 起点坐标 (x, y)
  cxt.lineTo(200, 100) // 终点坐标 (x, y)
  cxt.stroke() // 将起点和终点连接起来
</script>
复制代码

moveTolineTostroke 方法暂时可以不用管,它们的作用是绘制图形,这些方法在后面会讲到~

注意点

1、默认宽高

canvas默认的 宽度(300px) 和 高度(150px)

如果不在 canvas 上设置宽高,那 canvas 元素的默认宽度是300px,默认高度是150px。

2、设置 canvas 宽高

canvas 元素提供了 widthheight 两个属性,可设置它的宽高。

需要注意的是,这两个属性只需传入数值,不需要传入单位(比如 px 等)。

<canvas width="600" height="400"></canvas>
复制代码

3、不能通过 CSS 设置画布的宽高

使用 css 设置 canvas 的宽高,会出现 内容被拉伸 的后果!!!

03.png

<style>
  #c {
    width: 400px;
    height: 400px;
    border: 1px solid #ccc;
  }
</style>

<canvas id="c"></canvas>

<script>
  // 1、获取canvas对象
  const cnv = document.getElementById('c')

  // 2、获取canvas上下文环境对象
  const cxt = cnv.getContext('2d')

  // 3、绘制图形
  cxt.moveTo(100, 100) // 起点
  cxt.lineTo(200, 100) // 终点
  cxt.stroke() // 将起点和终点连接起来

  console.log(cnv.width) // 获取 canvas 的宽度,输出:300
  console.log(cnv.height) // 获取 canvas 的高度,输出:150
</script>
复制代码

canvas 的默认宽度是300px,默认高度是150px。

  1. 如果使用 css 修改 canvas 的宽高(比如本例变成 400px * 400px),那宽度就由 300px 拉伸到 400px,高度由 150px 拉伸到 400px。
  2. 使用 js 获取 canvas 的宽高,此时返回的是 canvas 的默认值。

最后出现的效果如上图所示。

4、线条默认宽度和颜色

线条的默认宽度是 1px ,默认颜色是黑色。

但由于默认情况下 canvas 会将线条的中心点和像素的底部对齐,所以会导致显示效果是 2px 和非纯黑色问题。

5、IE兼容性高

暂时只有 IE 9 以上才支持 canvas 。但好消息是 IE 已经有自己的墓碑了。

如需兼容 IE 7 和 8 ,可以使用 ExplorerCanvas[3] 。但即使是使用了 ExplorerCanvas 仍然会有所限制,比如无法使用 fillText() 方法等。

基础图形

坐标系

在绘制基础图形之前,需要先搞清除 Canvas 使用的坐标系。

Canvas 使用的是 W3C 坐标系 ,也就是遵循我们屏幕、报纸的阅读习惯,从上往下,从左往右。

04.jpg

W3C 坐标系数学直角坐标系X轴 是一样的,只是 Y轴 的反向相反。

W3C 坐标系Y轴 正方向向下。

直线

一条直线

最简单的起步方式是画一条直线。这里所说的 “直线” 是几何学里的 “线段” 的意思。

需要用到这3个方法:

  1. moveTo(x1, y1):起点坐标 (x, y)
  2. lineTo(x2, y2):下一个点的坐标 (x, y)
  3. stroke():将所有坐标用一条线连起来

起步阶段可以先这样理解。

05.png

<canvas id="c" style="border: 1px solid #ccc;"></canvas>

<script>
  const cnv = document.getElementById('c')
  const cxt = cnv.getContext('2d')

  // 绘制直线
  cxt.moveTo(50, 100) // 起点坐标
  cxt.lineTo(200, 50) // 下一个点的坐标
  cxt.stroke() // 将上面的坐标用一条线连接起来
</script>
复制代码

上面的代码所呈现的效果,可以看下图解释(手不太聪明,画得不是很标准,希望能看懂)

06.jpg

多条直线

如需画多条直线,可以用会上面那几个方法。

07.png

<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>

<script>
  const cnv = document.getElementById('c')
  const cxt = cnv.getContext('2d')

  cxt.moveTo(20, 100)
  cxt.lineTo(200, 100)
  cxt.stroke()

  cxt.moveTo(20, 120.5)
  cxt.lineTo(200, 120.5)
  cxt.stroke()
</script>
复制代码

仔细观察一下,为什么两条线的粗细不一样的?

明明使用的方法都是一样的,只是第二条直线的 Y轴 的值是有小数点。

答:默认情况下 canvas 会将线条的中心点和像素的底部对齐,所以会导致显示效果是 2px 和非纯黑色问题。

08.jpg

上图每个格子代表 1px

线的中心点会和画布像素点的底部对齐,所以会线中间是黑色的,但由于一个像素就不能再切割了,所以会有半个像素被染色,就变成了浅灰色。

所以如果你设置的 Y轴 值是一个整数,就会出现上面那种情况。

设置样式

  • lineWidth:线的粗细
  • strokeStyle:线的颜色
  • lineCap:线帽:默认: butt; 圆形: round; 方形: square

09.png

<canvas id="c" style="border: 1px solid #ccc;"></canvas>

<script>
  const cnv = document.getElementById('c')
  const cxt = cnv.getContext('2d')

  // 绘制直线
  cxt.moveTo(50, 50)
  cxt.lineTo(200, 50)

  // 修改直线的宽度
  cxt.lineWidth = 20

  // 修改直线的颜色
  cxt.strokeStyle = 'pink'

  // 修改直线两端样式
  cxt.lineCap = 'round' // 默认: butt; 圆形: round; 方形: square

  cxt.stroke()
</script>
复制代码

新开路径

开辟新路径的方法:

  • beginPath()

在绘制多条线段的同时,还要设置线段样式,通常需要开辟新路径。

要不然样式之间会相互污染。

比如这样

10.png

<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>

<script>
  const cnv = document.getElementById('c')
  const cxt = cnv.getContext('2d')

  // 第一条线
  cxt.moveTo(20, 100)
  cxt.lineTo(200, 100)
  cxt.lineWidth = 10
  cxt.strokeStyle = 'pink'
  cxt.stroke()

  // 第二条线
  cxt.moveTo(20, 120.5)
  cxt.lineTo(200, 120.5)
  cxt.stroke()
</script>
复制代码

如果不想相互污染,需要做2件事:

  1. 使用 beginPath() 方法,重新开一个路径
  2. 设置新线段的样式(必须项)

如果上面2步却了其中1步都会有影响。

只使用 beginPath()

11.png

<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>

<script>
  const cnv = document.getElementById('c')
  const cxt = cnv.getContext('2d')

  // 第一条线
  cxt.moveTo(20, 100)
  cxt.lineTo(200, 100)
  cxt.lineWidth = 10
  cxt.strokeStyle = 'pink'
  cxt.stroke()

  // 第二条线
  cxt.beginPath() // 重新开启一个路径
  cxt.moveTo(20, 120.5)
  cxt.lineTo(200, 120.5)
  cxt.stroke()
</script>
复制代码

第一条线的样式会影响之后的线。

但如果使用了 beginPath() ,后面的线段不会影响前面的线段。

12.png

<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>

<script>
  const cnv = document.getElementById('c')
  const cxt = cnv.getContext('2d')

  // 第一条线
  cxt.moveTo(20, 100)
  cxt.lineTo(200, 100)
  cxt.stroke()

  // 第二条线
  cxt.beginPath() // 重新开启一个路径
  cxt.moveTo(20, 120.5)
  cxt.lineTo(200, 120.5)
  cxt.lineWidth = 4
  cxt.strokeStyle = 'red'
  cxt.stroke()
</script>
复制代码

设置新线段的样式,没使用 beginPath() 的情况

这个情况会反过来,后面的线能影响前面的线。

13.png

<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>

<script>
  const cnv = document.getElementById('c')
  const cxt = cnv.getContext('2d')

  // 第一条线
  cxt.moveTo(20, 100)
  cxt.lineTo(200, 100)
  cxt.lineWidth = 10
  cxt.strokeStyle = 'pink'
  cxt.stroke()

  // 第二条线
  cxt.moveTo(20, 120.5)
  cxt.lineTo(200, 120.5)
  cxt.lineWidth = 4
  cxt.strokeStyle = 'red'
  cxt.stroke()
</script>
复制代码

正确的做法

在设置 beginPath() 的同时,也各自设置样式。这样就能做到相互不影响了。

14.png

<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>

<script>
  const cnv = document.getElementById('c')
  const cxt = cnv.getContext('2d')

  cxt.moveTo(20, 100)
  cxt.lineTo(200, 100)
  cxt.lineWidth = 10
  cxt.strokeStyle = 'pink'
  cxt.stroke()

  cxt.beginPath() // 重新开启一个路径
  cxt.moveTo(20, 120.5)
  cxt.lineTo(200, 120.5)
  cxt.lineWidth = 4
  cxt.strokeStyle = 'red'
  cxt.stroke()
</script>
复制代码

折线

直线 差不多,都是使用 moveTo()lineTo()stroke() 方法可以绘制折线。

15.png

<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>

<script>
  const cnv = document.getElementById('c')
  const cxt = cnv.getContext('2d')

  cxt.moveTo(50, 200)
  cxt.lineTo(100, 50)
  cxt.lineTo(200, 200)
  cxt.lineTo(250, 50)

  cxt.stroke()
</script>
复制代码

画这种折线,最好在草稿纸上画一个坐标系,自己计算并描绘一下每个点大概在什么什么位置,最后在 canvas 中看看效果。

矩形

根据前面的基础,我们可以 使用线段来描绘矩形,但 canvas 也提供了 rect() 等方法可以直接生成矩形。

使用线段描绘矩形

可以使用前面画线段的方法来绘制矩形

16.png

canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>

<script>
 const cnv = document.getElementById('c')
 const cxt = cnv.getContext('2d')

 // 绘制矩形
 cxt.moveTo(50, 50)
 cxt.lineTo(200, 50)
 cxt.lineTo(200, 120)
 cxt.lineTo(50, 120)
 cxt.lineTo(50, 50) // 需要闭合,又或者使用 closePath() 方法进行闭合,推荐使用 closePath()

 cxt.stroke()
</script>
复制代码

上面的代码几个点分别对应下图。

17.jpg

使用 strokeRect() 描边矩形

  • strokeStyle:设置描边的属性(颜色、渐变、图案)
  • strokeRect(x, y, width, height):描边矩形(x和y是矩形左上角起点;width 和 height 是矩形的宽高)
  • strokeStyle 必须写在 strokeRect() 前面,不然样式不生效。

18.png

<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>

<script>
  const cnv = document.getElementById('c')
  const cxt = cnv.getContext('2d')

  // strokeStyle 属性
  // strokeRect(x, y, width, height) 方法
  cxt.strokeStyle = 'pink'
  cxt.strokeRect(50, 50, 200, 100)
</script>
复制代码

上面的代码可以这样理解

19.jpg

使用 fillRect() 填充矩形

fillRect()strokeRect() 方法差不多,但 fillRect() 的作用是填充。

需要注意的是,fillStyle 必须写在 fillRect() 之前,不然样式不生效。

20.png

<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>

<script>
  const cnv = document.getElementById('c')
  const cxt = cnv.getContext('2d')

  // fillStyle 属性
  // fillRect(x, y, width, height) 方法
  cxt.fillStyle = 'pink'
  cxt.fillRect(50, 50, 200, 100) // fillRect(x, y, width, height)
</script>
复制代码

同时使用 strokeRect()fillRect()

同时使用 strokeRect()fillRect() 会产生描边和填充的效果

21.png

<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>

<script>
  const cnv = document.getElementById('c')
  const cxt = cnv.getContext('2d')

  cxt.strokeStyle = 'red'
  cxt.strokeRect(50, 50, 200, 100) // strokeRect(x, y, width, height)
  cxt.fillStyle = 'yellow'
  cxt.fillRect(50, 50, 200, 100) // fillRect(x, y, width, height)
</script>
复制代码

使用 rect() 生成矩形

rect()fillRect() 、strokeRect() 的用法差不多,唯一的区别是:

strokeRect()fillRect() 这两个方法调用后会立即绘制;rect() 方法被调用后,不会立刻绘制矩形,而是需要调用 stroke()fill() 辅助渲染。

22.png

<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>

<script>
  const cnv = document.getElementById('c')
  const cxt = cnv.getContext('2d')

  cxt.strokeStyle = 'red'
  cxt.fillStyle = 'pink'

  cxt.rect(50, 50, 200, 100) // rect(x, y, width, height)

  cxt.stroke()
  cxt.fill()
</script>
复制代码

等价公式:

cxt.strokeStyle = 'red',
cxt.rect(50, 50, 200, 100)
cxt.stroke()

// 等价于
cxt.strokeStyle = 'red'
cxt.strokerect(50, 50, 200, 100)


// -----------------------------


cxt.fillStyle = 'hotpink'
cxt.rect(50, 50, 200, 100)
cxt.fill()

// 等价于
cxt.fillStyle = 'yellowgreen'
cxt.fillRect(50, 50, 200, 100)
复制代码

使用 clearRect() 清空矩形

使用 clearRect() 方法可以清空指定区域。

clearRect(x, y, width, height)
复制代码

其语法和创建 cxt.rect() 差不多。

23.png

<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>

<script>
  const cnv = document.getElementById('c')
  const cxt = cnv.getContext('2d')

  cxt.fillStyle = 'pink' // 设置填充颜色
  cxt.fillRect(50, 50, 200, 200) // 填充矩形

  cxt.clearRect(60, 60, 180, 90) // 清空矩形
</script>
复制代码

清空画布

canvas 画布元素是矩形,所以可以通过下面的代码把整个画布清空掉。

// 省略部分代码

cxt.clearRect(0, 0, cnv.width, cnv.height)
复制代码

要清空的区域:从画布左上角开始,直到画布的宽和画布的高为止。

多边形

Canvas 要画多边形,需要使用 moveTo()lineTo()closePath()

三角形

虽然三角形是常见图形,但 canvas 并没有提供类似 rect() 的方法来绘制三角形。

需要确定三角形3个点的坐标位置,然后使用 stroke() 或者 fill() 方法生成三角形。

24.png

<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>

<script>

  const cnv = document.getElementById('c')
  const cxt = cnv.getContext('2d')

  cxt.moveTo(50, 50)
  cxt.lineTo(200, 50)
  cxt.lineTo(200, 200)

  // 注意点:如果使用 lineTo 闭合图形,是不能很好闭合拐角位的。
  cxt.lineTo(50, 50) // 闭合

  cxt.stroke()

</script>
复制代码

注意,默认情况下不会自动从最后一个点连接到起点。最后一步需要设置一下 cxt.lineTo(50, 50) ,让它与 cxt.moveTo(50, 50) 一样。这样可以让路径回到起点,形成一个闭合效果。

但这样做其实是有点问题的,而且也比较麻烦,要记住起始点坐标。

上面的闭合操作,如果遇到设置了 lineWidth 或者 lineJoin 就会有问题,比如:

25.png

// 省略部分代码
cxt.lineWidth = 20
复制代码

当线段变粗后,起始点和结束点的链接处,拐角就出现“不正常”现象。

如果需要真正闭合,可以使用 closePath() 方法。

26.png

<pre data-tool="mdnice编辑器" style="margin: 10px 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(0, 0, 0);font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: left;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;background-color: rgb(255, 255, 255);text-decoration-style: initial;text-decoration-color: initial;">```
<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;line-height: 26px;"><<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">canvas <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">id=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"c" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">width=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"300" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">height=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"300" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">style=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"border: 1px solid #ccc;"></<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">canvas><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;line-height: 26px;"><<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">script><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(166, 38, 164);line-height: 26px;">const cnv = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(193, 132, 1);line-height: 26px;">document.getElementById(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'c')<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(166, 38, 164);line-height: 26px;">const cxt = cnv.getContext(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'2d')<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.moveTo(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">50, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">50)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.lineTo(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">200, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">50)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.lineTo(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">200, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">200)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(160, 161, 167);font-style: italic;line-height: 26px;">// 手动闭合<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.closePath()<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.lineJoin = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'miter' <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(160, 161, 167);font-style: italic;line-height: 26px;">// 线条连接的样式。miter: 默认; bevel: 斜面; round: 圆角<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.lineWidth = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">20<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.stroke()<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br></<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">script><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>复制代码<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>

使用 `cxt.closePath()` 可以自动将终点和起始点连接起来,此时看上去就正常多了。


### 菱形

有一组邻边相等的平行四边形是菱形

![](https://oss-cn-hangzhou.aliyuncs.com/codingsky/cdn/img/2022-08-04/1ad6e769a674d23ac7947e64ce70d869)
27.png```
<pre data-tool="mdnice编辑器" style="margin: 10px 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(0, 0, 0);font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: left;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;background-color: rgb(255, 255, 255);text-decoration-style: initial;text-decoration-color: initial;">```
<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;line-height: 26px;"><<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">canvas <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">id=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"c" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">width=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"300" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">height=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"300" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">style=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"border: 1px solid #ccc;"></<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">canvas><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;line-height: 26px;"><<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">script><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(166, 38, 164);line-height: 26px;">const cnv = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(193, 132, 1);line-height: 26px;">document.getElementById(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'c')<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(166, 38, 164);line-height: 26px;">const cxt = cnv.getContext(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'2d')<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.moveTo(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">150, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">50)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.lineTo(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">250, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">100)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.lineTo(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">150, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">150)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.lineTo(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">50, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">100)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.closePath()<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.stroke()<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br></<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">script><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>复制代码<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>

要绘制直线类型的图形,在草稿纸上标记出起始点和每个拐角的点,然后再连线即可。相对曲线图形来说,直线图形是比较容易的。


圆形
--

绘制圆形的方法是 `arc()`。

**语法:**
```
arc(x, y, r, sAngle, eAngle,counterclockwise)

复制代码

``` ```
  • xy: 圆心坐标
  • r: 半径
  • sAngle: 开始角度
  • eAngle: 结束角度
  • counterclockwise: 绘制方向(true: 逆时针; false: 顺时针),默认 false

28.jpg开始角度和结束角度,都是以弧度为单位。例如 180°就写成 Math.PI ,360°写成 Math.PI * 2 ,以此类推。

在实际开发中,为了让自己或者别的开发者更容易看懂弧度的数值,1°应该写成 Math.PI / 180

  • 100°: 100 * Math.PI / 180
  • 110°: 110 * Math.PI / 180
  • 241°: 241 * Math.PI / 180

注意:绘制圆形之前,必须先调用 beginPath() 方法!!!在绘制完成之后,还需要调用 closePath() 方法!!!

29.png```

```
<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;">canvas>



<script>

  const cnv = document.getElementById('c')

  const cxt = cnv.getContext('2d')



  cxt.beginPath()

  cxt.arc(150, 150, 80, 0, 360 * Math.PI / 180)

  cxt.closePath()



  cxt.stroke()

script>

复制代码

``` ```

半圆

如果使用 arc() 方法画圆时,没做到刚好绕完一周(360°)就直接闭合路径,就会出现半圆的状态。

30.png```

```
<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;">canvas>



<script>

  const cnv = document.getElementById('c')

  const cxt = cnv.getContext('2d')



  cxt.beginPath()

  cxt.arc(150, 150, 100, 0, 180 * Math.PI / 180) // 顺时针

  cxt.closePath()



  cxt.stroke()

script>

复制代码

``` ```

上面的代码中,cxt.arc 最后一个参数没传,默认是 false ,所以是顺时针绘制。

31.jpg如果希望半圆的弧面在上方,可以将 cxt.arc 最后一个参数设置成 true

32.png```

```
<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;">canvas>



<script>

  const cnv = document.getElementById('c')

  const cxt = cnv.getContext('2d')



  cxt.beginPath()

  cxt.arc(150, 150, 100, 0, 180 * Math.PI / 180, true)

  cxt.closePath()



  cxt.stroke()

script>

复制代码

``` ```

弧线

使用 arc() 方法画半圆时,如果最后不调用 closePath() 方法,就不会出现闭合路径。也就是说,那是一条弧线。

canvas 中,画弧线有2中方法:arc()arcTo()

arc() 画弧线

如果想画一条 0° ~ 30° 的弧线,可以这样写

33.png```

```
<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;">canvas>



<script>

  const cnv = document.getElementById('c')

  const cxt = cnv.getContext('2d')



  cxt.beginPath()

  cxt.arc(150, 150, 100, 0, 30 * Math.PI / 180)



  cxt.stroke()

script>

复制代码

``` ```

原理如下图所示,红线代表画出来的那条弧线。

34.jpg

arcTo() 画弧线

arcTo() 的使用方法会更加复杂,如果初学看不太懂的话可以先跳过,看完后面的再回来补补。

语法:

<pre data-tool="mdnice编辑器" style="margin: 10px 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(0, 0, 0);font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: left;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;background-color: rgb(255, 255, 255);text-decoration-style: initial;text-decoration-color: initial;">```
arcTo(cx, cy, x2, y2, radius)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>复制代码

- `cx`: 两切线交点的横坐标
- `cy`: 两切线交点的纵坐标
- `x2`: 结束点的横坐标
- `y2`: 结束点的纵坐标
- `radius`: 半径

其中,`(cx, cy)` 也叫控制点,`(x2, y2)` 也叫结束点。

是不是有点奇怪,为什么没有 `x1` 和 `y1` ?

`(x1, y1)` 是开始点,通常是由 `moveTo()` 或者 `lineTo()` 提供。

`arcTo()` 方法利用 **开始点、控制点和结束点形成的夹角,绘制一段与夹角的两边相切并且半径为 `radius` 的圆弧**。

![](https://oss-cn-hangzhou.aliyuncs.com/codingsky/cdn/img/2022-08-04/519ae940dbfd3db437a271f73cb413f9)
35.jpg举个例子

![](https://oss-cn-hangzhou.aliyuncs.com/codingsky/cdn/img/2022-08-04/bec65dbd5581b07a3449f41714a17ad7)
36.png```
<pre data-tool="mdnice编辑器" style="margin: 10px 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(0, 0, 0);font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: left;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;background-color: rgb(255, 255, 255);text-decoration-style: initial;text-decoration-color: initial;">```
<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;line-height: 26px;"><<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">canvas <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">id=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"c" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">width=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"300" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">height=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"300" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">style=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"border: 1px solid #ccc;"></<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">canvas><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;line-height: 26px;"><<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">script><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(166, 38, 164);line-height: 26px;">const cnv = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(193, 132, 1);line-height: 26px;">document.getElementById(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'c')<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(166, 38, 164);line-height: 26px;">const cxt = cnv.getContext(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'2d')<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.moveTo(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">40, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">40)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.arcTo(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">120, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">40, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">120, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">120, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">80)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.stroke()<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br></<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">script><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>复制代码<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>


基础样式
====

前面学完基础图形,接下来可以开始了解一下如何设置元素的基础样式。


描边 stroke()
-----------

前面的案例中,其实已经知道使用 `stroke()` 方法进行描边了。这里就不再多讲这个方法。


线条宽度 lineWidth
--------------

`lineWidth` 默认值是 `1` ,默认单位是 `px`。

**语法:**
```
lineWidth = 线宽

复制代码

``` ```

37.png```

```
<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;">canvas>



<script>

  const cnv = document.getElementById('c')

  const cxt = cnv.getContext('2d')



  // 线宽 10

  cxt.beginPath()

  cxt.moveTo(50, 50)

  cxt.lineTo(250, 50)

  cxt.lineWidth = 10 // 设置线宽

  cxt.stroke()



  // 线宽 20

  cxt.beginPath()

  cxt.moveTo(50, 150)

  cxt.lineTo(250, 150)

  cxt.lineWidth = 20 // 设置线宽

  cxt.stroke()



  // 线宽 30

  cxt.beginPath()

  cxt.moveTo(50, 250)

  cxt.lineTo(250, 250)

  cxt.lineWidth = 30 // 设置线宽

  cxt.stroke()

script>

复制代码

``` ```

线条颜色 strokeStyle

使用 strokeStyle 可以设置线条颜色

语法:

<pre data-tool="mdnice编辑器" style="margin: 10px 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(0, 0, 0);font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: left;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;background-color: rgb(255, 255, 255);text-decoration-style: initial;text-decoration-color: initial;">```
strokeStyle = 颜色值<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>复制代码<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>

![](https://oss-cn-hangzhou.aliyuncs.com/codingsky/cdn/img/2022-08-04/f301508a0a6d337f1bfc88d04c7aaa1d)
38.png```
<pre data-tool="mdnice编辑器" style="margin: 10px 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(0, 0, 0);font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: left;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;background-color: rgb(255, 255, 255);text-decoration-style: initial;text-decoration-color: initial;">```
<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;line-height: 26px;"><<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">canvas <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">id=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"c" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">width=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"300" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">height=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"300" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">style=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"border: 1px solid #ccc;"></<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">canvas><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;line-height: 26px;"><<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">script><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(166, 38, 164);line-height: 26px;">const cnv = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(193, 132, 1);line-height: 26px;">document.getElementById(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'c')<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(166, 38, 164);line-height: 26px;">const cxt = cnv.getContext(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'2d')<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.moveTo(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">50, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">50)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.lineTo(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">250, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">50)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.lineWidth = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">20<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.strokeStyle = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'pink' <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(160, 161, 167);font-style: italic;line-height: 26px;">// 设置颜色<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.stroke()<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br></<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">script><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>复制代码<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>

为了展示方便,我将 `lineWidth` 设为 20。


线帽 lineCap
----------

线帽指的是线段的开始和结尾处的样式,使用 `lineCap` 可以设置

**语法:**
```
lineCap = '属性值'

复制代码

``` ```

属性值包括:

  • butt: 默认值,无线帽
  • square: 方形线帽
  • round: 圆形线帽

39.png```

```
<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;">canvas>



<script>

  const cnv = document.getElementById('c')

  const cxt = cnv.getContext('2d')



  // 设置线宽,方便演示

  cxt.lineWidth = 16



  // 默认线帽 butt

  cxt.beginPath()

  cxt.moveTo(50, 60)

  cxt.lineTo(250, 60)

  cxt.stroke()





  // 方形线帽 square

  cxt.beginPath()

  cxt.lineCap = 'square'

  cxt.moveTo(50, 150)

  cxt.lineTo(250, 150)

  cxt.stroke()





  // 圆形线帽 round

  cxt.beginPath()

  cxt.lineCap = 'round'

  cxt.moveTo(50, 250)

  cxt.lineTo(250, 250)

  cxt.stroke()

script>

复制代码

``` ```

使用 squareround 的话,会使线条变得稍微长一点点,这是给线条增加线帽的部分,这个长度在日常开发中需要注意。

线帽只对线条的开始和结尾处产生作用,对拐角不会产生任何作用。

拐角样式 lineJoin

如果需要设置拐角样式,可以使用 lineJoin

语法:

<pre data-tool="mdnice编辑器" style="margin: 10px 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(0, 0, 0);font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: left;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;background-color: rgb(255, 255, 255);text-decoration-style: initial;text-decoration-color: initial;">```
lineJoin = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'属性值'<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>复制代码<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>

属性值包括:

- `miter`: 默认值,尖角
- `round`: 圆角
- `bevel`: 斜角

![](https://oss-cn-hangzhou.aliyuncs.com/codingsky/cdn/img/2022-08-04/8f170f8243b68c1b2904ac29cfab38db)
40.png```
<pre data-tool="mdnice编辑器" style="margin: 10px 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(0, 0, 0);font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: left;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;background-color: rgb(255, 255, 255);text-decoration-style: initial;text-decoration-color: initial;">```
<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;line-height: 26px;"><<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">canvas <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">id=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"c" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">width=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"300" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">height=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"300" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">style=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"border: 1px solid #ccc;"></<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">canvas><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;line-height: 26px;"><<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">script><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(166, 38, 164);line-height: 26px;">const cnv = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(193, 132, 1);line-height: 26px;">document.getElementById(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'c')<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(166, 38, 164);line-height: 26px;">const cxt = cnv.getContext(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'2d')<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.lineWidth = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">20<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(160, 161, 167);font-style: italic;line-height: 26px;">// 默认,尖角<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.moveTo(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">50, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">40)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.lineTo(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">200, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">40)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.lineTo(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">200, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">90)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.stroke()<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(160, 161, 167);font-style: italic;line-height: 26px;">// 斜角 bevel<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.beginPath()<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.moveTo(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">50, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">140)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.lineTo(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">200, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">140)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.lineTo(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">200, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">190)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.lineJoin = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'bevel'<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.stroke()<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(160, 161, 167);font-style: italic;line-height: 26px;">// 圆角 round<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.beginPath()<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.moveTo(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">50, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">240)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.lineTo(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">200, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">240)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.lineTo(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">200, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">290)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.lineJoin = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'round'<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.stroke()<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br></<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">script><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>复制代码<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>


虚线 setLineDash()
----------------

使用 `setLineDash()` 方法可以将描边设置成虚线。

**语法:**
```
setLineDash([])

复制代码

``` ```

需要传入一个数组,且元素是数值型。

虚线分3种情况

  1. 只传1个值
  2. 有2个值
  3. 有3个以上的值

41.png```

```
<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;">canvas>



<script>

  const cnv = document.getElementById('c')

  const cxt = cnv.getContext('2d')



  cxt.lineWidth = 20

  cxt.strokeStyle = 'pink'



  cxt.moveTo(50, 50)

  cxt.lineTo(200, 50)

  cxt.setLineDash([10]) // 只传1个参数,实线与空白都是 10px

  cxt.stroke()





  cxt.beginPath()

  cxt.moveTo(50, 100)

  cxt.lineTo(200, 100)

  cxt.setLineDash([10, 20]) // 2个参数,此时,实线是 10px, 空白 20px

  cxt.stroke()





  cxt.beginPath()

  cxt.moveTo(50, 150)

  cxt.lineTo(200, 150)

  cxt.setLineDash([10, 20, 5]) // 传3个以上的参数,此例:10px实线,20px空白,5px实线,10px空白,20px实线,5px空白 ……



  cxt.stroke()

script>

复制代码

``` ```

此外,还可以始终 cxt.getLineDash() 获取虚线不重复的距离;

cxt.lineDashOffset 设置虚线的偏移位。

填充

使用 fill() 可以填充图形,根据前面的例子应该掌握了如何使用 fill()

42.png```

```
<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;">canvas>



<script>

  const cnv = document.getElementById('c')

  const cxt = cnv.getContext('2d')



  cxt.fillStyle = 'pink'



  cxt.rect(50, 50, 200, 100)



  cxt.fill()

script>

复制代码

``` ```

可以使用 fillStyle 设置填充颜色,默认是黑色。

非零环绕填充

在使用 fill() 方法填充时,需要注意一个规则:非零环绕填充

在使用 moveTolineTo 描述图形时,如果是按顺时针绘制,计数器会加1;如果是逆时针,计数器会减1。

当图形所处的位置,计数器的结果为0时,它就不会被填充。

这样说有点复杂,先看看例子

43.png```

```
<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;">canvas>



<script>

  const cnv = document.getElementById('c')

  const cxt = cnv.getContext('2d')



  // 外层矩形

  cxt.moveTo(50, 50)

  cxt.lineTo(250, 50)

  cxt.lineTo(250, 250)

  cxt.lineTo(50, 250)

  cxt.closePath()



  // 内层矩形

  cxt.moveTo(200, 100)

  cxt.lineTo(100, 100)

  cxt.lineTo(100, 200)

  cxt.lineTo(200, 200)

  cxt.closePath()

  cxt.fill()

script>

复制代码

``` ```

请看看上面的代码,我画了2个矩形,它们都没有用 beginPath() 方法开辟新路径。

44.png内层矩形是逆时针绘制的,所以内层的值是 -1 ,它又经过外层矩形,而外层矩形是顺时针绘制,所以经过外层时值 +1,最终内层的值为 0 ,所以不会被填充。

文本

Canvas 提供了一些操作文本的方法。

为了方便演示,我们先了解一下在 Canvas 中如何给本文设置样式。

样式 font

CSS 设置 font 差不多,Canvas 也可以通过 font 设置样式。

语法:

<pre data-tool="mdnice编辑器" style="margin: 10px 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(0, 0, 0);font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: left;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;background-color: rgb(255, 255, 255);text-decoration-style: initial;text-decoration-color: initial;">```
cxt.font = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'font-style font-variant font-weight font-size/line-height font-family'<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>复制代码<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>

如果需要设置字号 `font-size`,需要同事设置 `font-family`。
```
cxt.font = '30px 宋体'

复制代码

``` ```

描边 strokeText()

使用 strokeText() 方法进行文本描边

语法:

<pre data-tool="mdnice编辑器" style="margin: 10px 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(0, 0, 0);font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: left;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;background-color: rgb(255, 255, 255);text-decoration-style: initial;text-decoration-color: initial;">```
strokeText(text, x, y, maxWidth)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>复制代码

- `text`: 字符串,要绘制的内容
- `x`: 横坐标,文本**左边**要对齐的坐标(默认左对齐)
- `y`: 纵坐标,文本**底边**要对齐的坐标
- `maxWidth`: 可选参数,表示文本渲染的最大宽度(px),如果文本超出 `maxWidth` 设置的值,文本会被压缩。

![](https://oss-cn-hangzhou.aliyuncs.com/codingsky/cdn/img/2022-08-04/4906670cf3b43cae98f2d0012ab3759c)
45.png```
<pre data-tool="mdnice编辑器" style="margin: 10px 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(0, 0, 0);font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: left;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;background-color: rgb(255, 255, 255);text-decoration-style: initial;text-decoration-color: initial;">```
<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;line-height: 26px;"><<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">canvas <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">id=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"c" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">width=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"300" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">height=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"300" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">style=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"border: 1px solid #ccc;"></<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">canvas><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;line-height: 26px;"><<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">script><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(166, 38, 164);line-height: 26px;">const cnv = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(193, 132, 1);line-height: 26px;">document.getElementById(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'c')<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(166, 38, 164);line-height: 26px;">const cxt = cnv.getContext(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'2d')<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.font = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'60px Arial' <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(160, 161, 167);font-style: italic;line-height: 26px;">// 将字号设置成 60px,方便观察<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.strokeText(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'雷猴', <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">30, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">90)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br></<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">script><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>复制代码<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>


设置描边颜色 strokeStyle
------------------

使用 `strokeStyle` 设置描边颜色。

![](https://oss-cn-hangzhou.aliyuncs.com/codingsky/cdn/img/2022-08-04/f16dc8dfe52506bdbca263dbaa454469)
46.png```
<pre data-tool="mdnice编辑器" style="margin: 10px 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(0, 0, 0);font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: left;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;background-color: rgb(255, 255, 255);text-decoration-style: initial;text-decoration-color: initial;">```
<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;line-height: 26px;"><<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">canvas <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">id=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"c" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">width=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"300" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">height=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"300" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">style=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"border: 1px solid #ccc;"></<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">canvas><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;line-height: 26px;"><<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">script><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(166, 38, 164);line-height: 26px;">const cnv = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(193, 132, 1);line-height: 26px;">document.getElementById(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'c')<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(166, 38, 164);line-height: 26px;">const cxt = cnv.getContext(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'2d')<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.font = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'60px Arial' <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(160, 161, 167);font-style: italic;line-height: 26px;">// 将字号设置成 60px,方便观察<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.strokeStyle = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'pink' <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(160, 161, 167);font-style: italic;line-height: 26px;">// 设置文本描边颜色<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.strokeText(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'雷猴', <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">30, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">90)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br></<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">script><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>复制代码<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>


填充 fillText
-----------

使用 `fillText()` 可填充文本。

语法和 `strokeText()` 一样。
```
fillText(text, x, y, maxWidth)

复制代码

``` ```

47.png```

```
<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;">canvas>



<script>

  const cnv = document.getElementById('c')

  const cxt = cnv.getContext('2d')



  cxt.font = '60px Arial'

  cxt.fillText('雷猴', 30, 90)

script>

复制代码

``` ```

设置填充颜色 fillStyle

使用 fillStyle 可以设置文本填充颜色。

48.png```

```
<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;">canvas>



<script>

  const cnv = document.getElementById('c')

  const cxt = cnv.getContext('2d')



  cxt.font = '60px Arial'

  cxt.fillStyle = 'pink'

  cxt.fillText('雷猴', 30, 90)

script>

复制代码

``` ```

获取文本长度 measureText()

measureText().width 方法可以获取文本的长度,单位是 px

<pre data-tool="mdnice编辑器" style="margin: 10px 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(0, 0, 0);font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: left;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;background-color: rgb(255, 255, 255);text-decoration-style: initial;text-decoration-color: initial;">```
<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;line-height: 26px;"><<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">canvas <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">id=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"c" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">width=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"300" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">height=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"300" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">style=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"border: 1px solid #ccc;"></<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">canvas><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;line-height: 26px;"><<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">script><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(166, 38, 164);line-height: 26px;">const cnv = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(193, 132, 1);line-height: 26px;">document.getElementById(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'c')<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(166, 38, 164);line-height: 26px;">const cxt = cnv.getContext(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'2d')<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(166, 38, 164);line-height: 26px;">let text = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'雷猴'<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.font = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'bold 40px Arial'<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.fillText(text, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">40, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">80)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(193, 132, 1);line-height: 26px;">console.log(cxt.measureText(text).width) <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(160, 161, 167);font-style: italic;line-height: 26px;">// 80<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br></<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">script><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>复制代码<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>


水平对齐方式 textAlign
----------------

使用 `textAlign` 属性可以设置文字的水平对齐方式,一共有5个值可选

- `start`: 默认。在指定位置的横坐标开始。
- `end`: 在指定坐标的横坐标结束。
- `left`: 左对齐。
- `right`: 右对齐。
- `center`: 居中对齐。

![](https://oss-cn-hangzhou.aliyuncs.com/codingsky/cdn/img/2022-08-04/1552a63b1654e7063893ae537947cf25)
49.png红线是辅助参考线。
```
<canvas id="c" width="400" height="400" style="border: 1px solid #ccc;">canvas>



<script>

  const cnv = document.getElementById('c')

  const cxt = cnv.getContext('2d')



  // 竖向的辅助线(参考线,在画布中间)

  cxt.moveTo(200, 0)

  cxt.lineTo(200, 400)

  cxt.strokeStyle = 'red'

  cxt.stroke()



  cxt.font = '30px Arial'



  // 横坐标开始位对齐

  cxt.textAlign = 'start' // 默认值,

  cxt.fillText('雷猴 start', 200, 40)



  // 横坐标结束位对齐

  cxt.textAlign = 'end' // 结束对齐

  cxt.fillText('雷猴 end', 200, 100)



  // 左对齐

  cxt.textAlign = 'left' // 左对齐

  cxt.fillText('雷猴 left', 200, 160)



  // 右对齐

  cxt.textAlign = 'right' // 右对齐

  cxt.fillText('雷猴 right', 200, 220)



  // 居中对齐

  cxt.textAlign = 'center' // 右对齐

  cxt.fillText('雷猴 center', 200, 280)

script>

复制代码

``` ```

从上面的例子看,startleft 的效果好像是一样的,endright 也好像是一样的。

在大多数情况下,它们的确一样。但在某些国家或者某些场合,阅读文字的习惯是 从右往左 时,start 就和 right 一样了,endleft 也一样。这是需要注意的地方。

垂直对齐方式 textBaseline

使用 textBaseline 属性可以设置文字的垂直对齐方式。

在使用 textBaseline 前,需要自行了解 css 的文本基线。

50.png用一张网图解释一下基线

textBaseline 可选属性:

  • alphabetic: 默认。文本基线是普通的字母基线。
  • top: 文本基线是 em 方框的顶端。
  • bottom: 文本基线是 em 方框的底端。
  • middle: 文本基线是 em 方框的正中。
  • hanging: 文本基线是悬挂基线。

51.png红线是辅助参考线。

<pre data-tool="mdnice编辑器" style="margin: 10px 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(0, 0, 0);font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: left;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;background-color: rgb(255, 255, 255);text-decoration-style: initial;text-decoration-color: initial;">```
<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;line-height: 26px;"><<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">canvas <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">id=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"c" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">width=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"800" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">height=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"300" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">style=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"border: 1px solid #ccc;"></<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">canvas><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;line-height: 26px;"><<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">script><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(166, 38, 164);line-height: 26px;">const cnv = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(193, 132, 1);line-height: 26px;">document.getElementById(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'c')<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(166, 38, 164);line-height: 26px;">const cxt = cnv.getContext(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'2d')<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(160, 161, 167);font-style: italic;line-height: 26px;">// 横向的辅助线(参考线,在画布中间)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.moveTo(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">0, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">150)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.lineTo(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">800, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">150)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.strokeStyle = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'red'<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.stroke()<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.font = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'20px Arial'<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(160, 161, 167);font-style: italic;line-height: 26px;">// 默认 alphabetic<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.textBaseline = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'alphabetic'<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.fillText(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'雷猴 alphabetic', <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">10, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">150)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(160, 161, 167);font-style: italic;line-height: 26px;">// 默认 top<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.textBaseline = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'top'<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.fillText(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'雷猴 top', <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">200, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">150)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(160, 161, 167);font-style: italic;line-height: 26px;">// 默认 bottom<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.textBaseline = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'bottom'<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.fillText(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'雷猴 bottom', <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">320, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">150)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(160, 161, 167);font-style: italic;line-height: 26px;">// 默认 middle<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.textBaseline = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'middle'<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.fillText(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'雷猴 middle', <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">480, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">150)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(160, 161, 167);font-style: italic;line-height: 26px;">// 默认 hanging<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.textBaseline = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'hanging'<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  cxt.fillText(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'雷猴 hanging', <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">640, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">150)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br></<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">script><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>复制代码<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>

**注意:在绘制文字的时候,默认是以文字的左下角作为参考点进行绘制**


图片
==

在 `Canvas` 中可以使用 `drawImage()` 方法绘制图片。


渲染图片
----

渲染图片的方式有2中,一种是**在JS里加载图片再渲染**,另一种是**把DOM里的图片拿到 `canvas` 里渲染**。

**渲染的语法:**
```
drawImage(image, dx, dy)

复制代码

``` ```
  • image: 要渲染的图片对象。
  • dx: 图片左上角的横坐标位置。
  • dy: 图片左上角的纵坐标位置。

JS版

JS 里加载图片并渲染,有以下几个步骤:

  1. 创建 Image 对象
  2. 引入图片
  3. 等待图片加载完成
  4. 使用 drawImage() 方法渲染图片

52.png```

```
<canvas id="c" width="500" height="500" style="border: 1px solid #ccc;">canvas>



<script>

  const cnv = document.getElementById('c')

  const cxt = cnv.getContext('2d')



  // 1 创建 Image 对象

  const image = new Image()



  // 2 引入图片

  image.src = './images/dog.jpg'



  // 3 等待图片加载完成

  image.onload = () => {

    // 4 使用 drawImage() 方法渲染图片

    cxt.drawImage(image, 30, 30)

  }

script>

复制代码

``` ```

DOM版

53.png```

```
<style>

  #dogImg {

    display: none;

  }

style>



<img src="./images/dog.jpg" id="dogImg"/>

<canvas id="c" width="500" height="500" style="border: 1px solid #ccc;">canvas>



<script>

  const cnv = document.getElementById('c')

  const cxt = cnv.getContext('2d')



  const image = document.getElementById('dogImg')



  cxt.drawImage(image, 70, 70)

script>

复制代码

``` ```

因为图片是从 DOM 里获取到的,所以一般来说,只要在 window.onload 这个生命周期内使用 drawImage 都可以正常渲染图片。

本例使用了 css 的方式,把图片的 display 设置成 none 。因为我不想被 <img> 影响到本例讲解。

实际开发过程中按照实际情况设置即可。

设置图片宽高

前面的例子都是直接加载图片,图片默认的宽高是多少就加载多少。

如果需要指定图片宽高,可以在前面的基础上再添加两个参数:

<pre data-tool="mdnice编辑器" style="margin: 10px 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(0, 0, 0);font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: left;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;background-color: rgb(255, 255, 255);text-decoration-style: initial;text-decoration-color: initial;">```
drawImage(image, dx, dy, dw, dh)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>复制代码<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>

`image、 dx、 dy` 的用法和前面一样。

`dw` 用来定义图片的宽度,`dh` 定义图片的高度。

![](https://oss-cn-hangzhou.aliyuncs.com/codingsky/cdn/img/2022-08-04/d902b5ed312744a3a5011c2029caa6b6)
54.png```
<pre data-tool="mdnice编辑器" style="margin: 10px 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(0, 0, 0);font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: left;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;background-color: rgb(255, 255, 255);text-decoration-style: initial;text-decoration-color: initial;">```
<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;line-height: 26px;"><<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">canvas <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">id=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"c" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">width=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"500" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">height=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"500" <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">style=<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">"border: 1px solid #ccc;"></<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">canvas><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;line-height: 26px;"><<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">script><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(166, 38, 164);line-height: 26px;">const cnv = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(193, 132, 1);line-height: 26px;">document.getElementById(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'c')<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(166, 38, 164);line-height: 26px;">const cxt = cnv.getContext(<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'2d')<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(166, 38, 164);line-height: 26px;">const image = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(166, 38, 164);line-height: 26px;">new Image()<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  image.src = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(80, 161, 79);line-height: 26px;">'./images/dog.jpg'<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  image.onload = <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;line-height: 26px;"><span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;line-height: 26px;">() => {<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>    cxt.drawImage(image, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">30, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">30, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">100, <span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(152, 104, 1);line-height: 26px;">100)<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>  }<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br></<span style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;color: rgb(228, 86, 73);line-height: 26px;">script><br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>复制代码<br style="margin: 0px;padding: 0px;outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></br>

我把图片的尺寸设为 100px \* 100px,图片看上去比之前就小了很多。


截取图片
----

截图图片同样使用`drawImage()` 方法,只不过传入的参数数量比之前都多,而且顺序也有点不一样了。
```
drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)

复制代码

``` ```

以上参数缺一不可

  • image: 图片对象
  • sx: 开始截取的横坐标
  • sy: 开始截取的纵坐标
  • sw: 截取的宽度
  • sh: 截取的高度
  • dx: 图片左上角的横坐标位置
  • dy: 图片左上角的纵坐标位置
  • dw: 图片宽度
  • dh: 图片高度

55.png```

```
<canvas id="c" width="500" height="500" style="border: 1px solid #ccc;">canvas>



<script>

  const cnv = document.getElementById('c')

  const cxt = cnv.getContext('2d')



  const image = new Image()

  image.src = './images/dog.jpg'



  image.onload = () => {

    cxt.drawImage(image, 0, 0, 100, 100, 30, 30, 200, 200)

  }

script>

复制代码

``` ```

总结

本文主要讲解了在 Canvas 中绘制一些基础图形,还有一些基础样式设置。

还有更多高级的玩法会在之后的文章中讲到,比如渐变、投影、滤镜等等。

代码仓库

⭐雷猴 Canvas:https://gitee.com/k21vin/thunder-monkey-canvas

关于本文 作者:德育处主任

https://juejin.cn/post/7116784455561248775

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:1年以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:1年以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:1年以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:1年以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:1年以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:1年以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:1年以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:1年以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:1年以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:1年以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:1年以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:1年以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:1年以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:1年以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:1年以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:1年以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:1年以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:1年以前  |  398次阅读  |  详细内容 »
 相关文章
Android插件化方案 5年以前  |  237231次阅读
vscode超好用的代码书签插件Bookmarks 2年以前  |  8065次阅读
 目录