PixiJs学前篇(一):Canvas基础【绘制篇】🔥🔥

9,726 阅读12分钟

本文为稀土掘金技术社区首发签约文章,14天内禁止转载,14天后未获授权禁止转载,侵权必究!

大家好我是ndz,很高兴也很荣幸成为了一名稀土掘金技术社区签约作者,在这里真的很感谢平台给予的肯定和各位读者的支持,感谢 🙏 🙏 🙏。

本文为稀土掘金技术社区签约作者专栏 - 《从Canvas到PixiJs》 的第二篇文章,喜欢的小伙伴记得点赞加关注,以防需要用时回来不迷路 😂


前言

在之前的文章中其实也写过一篇Canvas的基础文章:案例+图解带你一文读懂Canvas🔥🔥(2W+字),但整体比较平铺直叙,并且因为掘金文章对字数的限制删除了很多案例,在本专栏中我会重新归纳总结,尽量让小伙伴们看着就懂、看完就会、学完就能写。人狠话不多直接上干货。

Canvas已悄悄让你不得不学它。

随着很多复杂场景的出现,前端的性能也越发值得大家的关注,尤其近几年随着在线教育、在线直播、可视化编辑、各种小游戏的火爆,前端性能的关注度疯狂的蹭蹭往上飙。

随着性能的不断优化,性能的上限和性价比却又值得大家深思,在一些特殊场景,真实DOM的性能远远比不上Canvas的渲染,毕竟Canvas的推出主打优势就是更快的渲染速度,因此在原有真实DOM渲染的基础上去做性能优化远远不如换一种方案,直接使用Canvas绘制来的实在。在如今已经有不少公司考虑采用Canvas渲染来尽可能的获得性能提升,尤其自从2021年5月11日开始Google官方更新 Google Docs 的呈现文档方式变更时声明:

We’re updating the way Google Docs renders documents. Over the course of the next several months, we’ll be migrating the underlying technical implementation of Docs from the current HTML-based rendering approach to a canvas-based approach to improve performance and improve consistency in how content appears across different platforms. 译文:我们正在更新Google文档渲染文档的方式。在接下来的几个月中,我们将迁移文档的基本技术实施,从当前基于HTML的渲染方法到基于帆布的方法,以提高性能并提高内容的一致性。

文章链接:Google文档现在将使用基于帆布的渲染:这可能会影响某些Chrome Extensions

鉴于人们对Google趋之若鹜的跟随心理,Google的每一次变革似乎都成了当下技术的趋势,当然这一次也不例外,Google Docs 决定更新为Canvas渲染以后,把Canvas推上了一个新的高度。

相关的的文章可以看这篇了解一下:The Future Web: Will Canvas Rendering Replace the DOM?

Canvas已悄悄成了web文本渲染的一种趋势,未来Canvas渲染是否会取代DOM渲染这个现在还不好断言,但Canvas的优势就放着这里,很多特定情况下如今DOM渲染已远远不如Canvas渲染,被替代已成为定局。

Canvas的创建

说了这么多下面开始我们Canvas基础的学习,首先咱们看看如何创建一个Canvas。

Canvas的创建其实就是一个HTML标签,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 创建</title>
</head>
<body>
  <canvas
    id="canvas"
    width="500" 
    height="500" 
    style="box-shadow: 0px 0px 5px #ccc; border-radius: 8px;">
    当前浏览器不支持canvas元素,请升级或更换浏览器!
  </canvas>
</body>
</html>

效果如下:

image.png

上面的示例我们已经创建了一个完整的Canvas案例,需要重点说明的是:

属性

上面的<canvas>标签中我们用到了四个属性,分别是:

  • id:画布的唯一标识,获取画布的时候可以用它
  • width:画布的宽度,这里需要说明在不设置画布宽度的时候,默认宽度为300像素
  • height:画布的高度,这里需要说明在不设置画布高度的时候,默认高度为150像素
  • style:画布的样式,例如正常情况下画布是没有边框或者阴影的,但上面示例中我们通过style属性给<canvas>标签设置了阴影和圆角样式。

兼容

在这里直接放一张 Can I Use 的详细兼容表。

image.png

如上图所示,虽然<canvas>最早是由 Apple 引入 WebKit,用于Mac OS X 的 Dashboard,可如今已经被所有主流的浏览器所支持。

绘制

Canvas的核心就是绘制内容,学会如何绘制元素其实整个Canvas的学习也就基本算是入门了。那么如何绘制呢?

绘制上下文

在Canvas的绘制中,Canvas本身是没有绘制能力的,它的所有绘制都是通过JavaScript来实现的,真正印证了阿特伍德定律:

any application that can be written in JavaScript, will eventually be written in JavaScript。
译文:任何可以用JavaScript来写的应用,最终都将用JavaScript来写。

言归正传,在Canvas没有绘制能力的情况下,JavaScript又如何在Canvas中实现元素的绘制呢?

这还得说到一个东西:绘制上下文

获取Canvas 绘制上下文的方法为:getContext(),正是这个方法让Canvas具备绘制的能力。

既然说到了这里那就补充一个方法:getWebGLContext(),这个方法可以让Canvas具备绘制能力,但和getContext()的区别是getWebGLContext()是用来给WebGL提供绘制上下文的。这里咱们主要说Canvas就不过多对getWebGLContext()方法进行展开说明了。言归正传咱们回到getContext()方法。

语法结构

getContext()方法的语法结构为:

canvas.getContext(contextType, contextAttributes)

参数说明:

  1. contextType 为绘制上下文的类型,类型参数有:
  • 2d:用于创建一个 CanvasRenderingContext2D 2D绘制上下文。

  • webgl:用于创建一个 WebGLRenderingContext 3D渲染上下文对象。且该类型只支持在实现WebGL版本1的浏览器上可用也就是 OpenGL ES 2.0。

  • webgl2:用于创建一个 WebGL2RenderingContext 3D渲染上下文对象。且该类型只支持在实现WebGL版本2的浏览器上可用也就是 OpenGL ES 3.0。

  • bitmaprenderer:用于创建一个只提供将 canvas 内容替换为指定ImageBitmap功能的ImageBitmapRenderingContext。

注意📢:在同一个Canvas上,使用相同的类型参数contextType多次调用getContext()方法只会返回同一个绘制上下文。

  1. contextAttributes 为绘制上下文的属性,这些属性相对比较多,可以设置单个也可以同时设置多个,下面列一下,方便大家了解:
  • 2D类型的参数有: (1)、alpha 它的值为Boolean类型,如果设置为false, 浏览器将认Canvas背景总是不透明的,这样可以做到一些性能提效。(2)、willReadFrequently,值也为Boolean类型,用于表明是否要重复操作,频繁调用getImageData()方法时能节省内存,但是仅Gecko内核浏览器支持。(3)、storage用于表明使用哪种方式存储,默认值 persisten,表示持久化存储。

  • 3D类型的参数有: (1)、alpha 值为Boolean类型,指示画布是否包含alpha缓冲区。 (2)、antialias 值为Boolean类型,指示是否开启抗锯齿。 (3)、depth 值为Boolean类型,表示绘图缓冲区的深度缓冲区至少为16位。 (4)、failIfMajorPerformanceCaveat值为Boolean类型,指示如果系统性能较低,是否创建上下文。 (5)、powerPreference:对用户代理的提示,指示GPU的哪种配置适合WebGL上下文。可能的值是: default: 自动选择模式,自动决定哪种GPU配置最合适,为默认值。 high-performance: 高性能模式,优先考虑渲染性能而不是功耗。 low-power: 节能模式,优先考虑节能而不是渲染性能。 (6)、premultipliedAlpha 值为Boolean类型,表示页面合成器将假定绘图缓冲区包含具有预乘alpha的颜色。 (7)、preserveDrawingBuffer 值为Boolean类型,如果值为true,则不会清除缓冲区并保留其值,直到被清除或被使用者覆盖。 (8)、stencil 值为Boolean类型,表示绘图缓冲区具有至少8位的模板缓冲区。

了解了语法以后,咱们开始看看如何获取上下文。代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 创建</title>
</head>
<body>
  <canvas
    id="canvas"
    width="500" 
    height="500" 
    style="box-shadow: 0px 0px 5px #ccc; border-radius: 8px;">
    当前浏览器不支持canvas元素,请升级或更换浏览器!
  </canvas>
  <script>
    const canvas = document.getElementById('canvas');
    const ctx = canvas.getContext('2d');
    console.log(ctx) // CanvasRenderingContext2D ...
  </script>
</body>
</html>

效果如下:

image.png

从上图咱们可以看出,通过getContext()方法我们获取到了Canvas的绘制上下文。在上图的折叠属性canvas中,其实还有很多属性,感兴趣的小伙伴可以打印了看一下都有哪些东西。

image.png

绘制方式

想要绘制出效果,我们还需要了解一下绘制的方法,我这边把绘制分为两种,描边和填充,对应的方法为 stroke()fill()

stroke()

描边

fill()

填充

具体效果我们一起举个例子看一下就清楚了。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 创建</title>
</head>
<body>
  <canvas
    id="canvas"
    width="500" 
    height="500" 
    style="box-shadow: 0px 0px 5px #ccc; border-radius: 8px;">
    当前浏览器不支持canvas元素,请升级或更换浏览器!
  </canvas>
  <script>
    const canvas = document.getElementById('canvas'); // 获取Canvas
    const ctx = canvas.getContext('2d'); // 获取绘制上下文
    ctx.rect(50, 50, 200,100) // 绘制矩形
    ctx.stroke() // 描边一个矩形轮廓
    ctx.beginPath() // 开启新路径
    ctx.rect(50, 200, 200,100) // 绘制矩形
    ctx.fill() // 填充一个矩形

  </script>
</body>
</html>

这里咱们先不管矩形为什么这么绘制,beginPath()方法又是用来干啥的,咱们直接看效果,看看描边stroke()和填充fill()绘制出来的矩形有什么不同。

image.png

如上图所示,描边就是绘制出一个矩形的轮廓,填充就是使用默认的颜色(黑色)填充一个矩形块。

那我们如何改变描边和填充的样式呢?

样式设置

描边和填充的默认样式都是黑色,下面我们可以通过两个属性设置他们的样式,分别是strokeStylefillStyle 属性

strokeStyle

描边的样式

fillStyle

填充的样式

一起举个例子看一下

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 创建</title>
</head>
<body>
  <canvas
    id="canvas"
    width="500" 
    height="500" 
    style="box-shadow: 0px 0px 5px #ccc; border-radius: 8px;">
    当前浏览器不支持canvas元素,请升级或更换浏览器!
  </canvas>
  <script>
    const canvas = document.getElementById('canvas'); // 获取Canvas
    const ctx = canvas.getContext('2d'); // 获取绘制上下文
    ctx.strokeStyle = "#f00" // 描边样式设置为红色
    ctx.rect(50, 50, 200,100) // 绘制矩形
    ctx.stroke() // 描边一个矩形轮廓
    ctx.beginPath() // 开启新路径
    ctx.fillStyle = "#0f0" // 描边样式设置为绿色
    ctx.rect(50, 200, 200,100) // 绘制矩形
    ctx.fill() // 填充一个矩形
  </script>
</body>
</html>

设置了样式以后的效果为:

image.png

值得注意的是,strokeStylefillStyle 属性的设置是一次设置永久有效的,想要改变必须重新设置其他值来覆盖原有的值。

举个例子看一下

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 创建</title>
</head>
<body>
  <canvas
    id="canvas"
    width="500" 
    height="500" 
    style="box-shadow: 0px 0px 5px #ccc; border-radius: 8px;">
    当前浏览器不支持canvas元素,请升级或更换浏览器!
  </canvas>
  <script>
    const canvas = document.getElementById('canvas'); // 获取Canvas
    const ctx = canvas.getContext('2d'); // 获取绘制上下文
    ctx.strokeStyle = "#f00" // 描边样式设置为红色
    // 矩形一
    ctx.rect(50, 50, 200, 100) // 绘制矩形
    ctx.stroke() // 描边一个矩形轮廓
   
    // 矩形二
    ctx.beginPath() // 开启新路径
    ctx.rect(50, 200, 200, 100) // 绘制矩形
    ctx.stroke() // 描边一个矩形轮廓
 
    // 矩形三
    ctx.beginPath() // 开启新路径
    ctx.strokeStyle = "#00f" // 描边样式重新设置为蓝色
    ctx.rect(50, 350, 200, 100) // 绘制矩形
    ctx.stroke() // 描边一个矩形轮廓

  </script>
</body>
</html>

效果如下

image.png

如上图所示,矩形一和矩形二沿用了最开始设置的 strokeStyle属性(红色),矩形三重新设置strokeStyle属性为蓝色以后,矩形三变成了蓝色的矩形。

这说明strokeStyle属性一旦设置以后是一直有效的,直到被覆盖。

fillStyle属性和strokeStyle属性一样,一旦设置以后是一直有效的,直到被覆盖。

基本绘制形状

在Canvas的绘制中,基本绘制形状主要有:直线三角形矩形圆和圆弧椭圆贝塞尔曲线

下面我们依次介绍一下这些基本绘制形状。

直线

直线的绘制就是设置两个点,然后连接这两个点形成一条直线,那么这两个点如何设置呢?

moveTo(x, y)

设置初始位置,参数为初始位置x和y的坐标点

lineTo(x, y)

设置指定位置,参数为指定位置x和y的坐标点

举个例子看一下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 创建</title>
</head>
<body>
  <canvas
    id="canvas"
    width="500" 
    height="500" 
    style="box-shadow: 0px 0px 5px #ccc; border-radius: 8px;">
    当前浏览器不支持canvas元素,请升级或更换浏览器!
  </canvas>
  <script>
    const canvas = document.getElementById('canvas'); // 获取Canvas
    const ctx = canvas.getContext('2d'); // 获取绘制上下文
    ctx.strokeStyle = "#f00" // 描边样式设置为红色
    // 画一条(50, 50) 到 (400, 50)的直线
    ctx.moveTo(50, 50) 
    ctx.lineTo(400, 50)
    ctx.stroke() 

    // 连续的直线只需要设置一个起始点
    ctx.moveTo(50, 100) 
    ctx.lineTo(50, 400)
    ctx.lineTo(400, 400)
    ctx.stroke() 
  </script>
</body>
</html>

效果如下:

image.png

样式

直线的样式可以通过一系列属性来设置,

lineWidth

设置直线的粗细,默认值为1,且属性值必须为正数。

举个例子看一下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 创建</title>
</head>
<body>
  <canvas
    id="canvas"
    width="500" 
    height="500" 
    style="box-shadow: 0px 0px 5px #ccc; border-radius: 8px;">
    当前浏览器不支持canvas元素,请升级或更换浏览器!
  </canvas>
  <script>
    const canvas = document.getElementById('canvas'); // 获取Canvas
    const ctx = canvas.getContext('2d'); // 获取绘制上下文
    ctx.strokeStyle = "#f00" // 描边样式设置为红色
    
    // 画一条(50, 50) 到 (400, 50)的直线
    ctx.moveTo(50, 50) 
    ctx.lineTo(400, 50)
    ctx.stroke() 

    ctx.beginPath() // 开启新路径

    // 连续的直线只需要设置一个起始点
    ctx.lineWidth = 10
    ctx.moveTo(50, 100) 
    ctx.lineTo(50, 400)
    ctx.lineTo(400, 400)
    ctx.stroke() 
  </script>
</body>
</html>

效果如下:

image.png

lineCap

设置直线端点显示的样式。可选值为:butt,round 和 square。默认是 butt。

举个例子看一下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 创建</title>
</head>
<body>
  <canvas
    id="canvas"
    width="500" 
    height="500" 
    style="box-shadow: 0px 0px 5px #ccc; border-radius: 8px;">
    当前浏览器不支持canvas元素,请升级或更换浏览器!
  </canvas>
  <script>
    const canvas = document.getElementById('canvas'); // 获取Canvas
    const ctx = canvas.getContext('2d'); // 获取绘制上下文
    ctx.strokeStyle = "#f00" // 描边样式设置为红色
    
    // lineCap 值为 butt
    ctx.lineWidth = 20;
    ctx.lineCap='butt'
    ctx.moveTo(50, 50);
    ctx.lineTo(400, 50);
    ctx.stroke();

    // lineCap 值为 round
    ctx.beginPath()
    ctx.lineWidth = 20;
    ctx.lineCap='round'
    ctx.moveTo(50, 100);
    ctx.lineTo(400, 100);
    ctx.stroke();

    // lineCap 值为 square
    ctx.beginPath()
    ctx.lineWidth = 20;
    ctx.lineCap='square'
    ctx.moveTo(50, 150);
    ctx.lineTo(400, 150);
    ctx.stroke();


  </script>
</body>
</html>

效果如下:

image.png

lineJoin

设置两线段连接处所显示的样子。可选值为:round, bevel 和 miter。默认是 miter。

举个例子看一下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 创建</title>
</head>
<body>
  <canvas
    id="canvas"
    width="500" 
    height="500" 
    style="box-shadow: 0px 0px 5px #ccc; border-radius: 8px;">
    当前浏览器不支持canvas元素,请升级或更换浏览器!
  </canvas>
  <script>
    const canvas = document.getElementById('canvas'); // 获取Canvas
    const ctx = canvas.getContext('2d'); // 获取绘制上下文
    ctx.strokeStyle = "#f00" // 描边样式设置为红色
    
    // lineJoin 值为 miter
    ctx.beginPath()
    ctx.lineWidth = 10;
    ctx.lineJoin='miter'
    ctx.moveTo(50, 20);
    ctx.lineTo(150, 140);
    ctx.lineTo(250, 20);
    ctx.stroke();

    // lineJoin 值为 round
    ctx.beginPath()
    ctx.lineWidth = 10;
    ctx.lineJoin='round'
    ctx.moveTo(50, 100);
    ctx.lineTo(150, 220);
    ctx.lineTo(250, 100);
    ctx.stroke();

    // lineJoin 值为 bevel
    ctx.beginPath()
    ctx.lineWidth = 10;
    ctx.lineJoin='bevel'
    ctx.moveTo(50, 180);
    ctx.lineTo(150, 300);
    ctx.lineTo(250, 180);
    ctx.stroke();

  </script>
</body>
</html>

效果如下:

image.png

miterLimit

设置当两条线相交时交接处最大长度;所谓交接处长度(斜接长度)是指线条交接处内角顶点到外角顶点的长度。

线段之间夹角比较大时,交点不会太远,但随着夹角变小,交点距离会呈指数级增大。

如果交点距离大于miterLimit值,连接效果会变成了 lineJoin = bevel 的效果。

举个例子看一下

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 创建</title>
</head>
<body>
  <canvas
    id="canvas"
    width="500" 
    height="500" 
    style="box-shadow: 0px 0px 5px #ccc; border-radius: 8px;">
    当前浏览器不支持canvas元素,请升级或更换浏览器!
  </canvas>
  <script>
    const canvas = document.getElementById('canvas'); // 获取Canvas
    const ctx = canvas.getContext('2d'); // 获取绘制上下文
    ctx.strokeStyle = "#f00" // 描边样式设置为红色

    // miterLimit为定值,角度越大
    ctx.beginPath()
      ctx.lineWidth = 5;
      ctx.lineJoin='miter'
      ctx.miterLimit = 10
      ctx.moveTo(0, 100);
      for (i = 0; i < 50 ; i++) {
        var dy = i % 2 == 0 ? 200 : 100;
        ctx.lineTo(Math.pow(i, 1.5) * 2, dy);
      }
      ctx.stroke();
      ctx.closePath();

  </script>
</body>
</html>

效果如下:

image.png

setLineDash/getLineDash

setLineDash 设置虚线样式。

getLineDash 返回虚线设置的样式,长度为非负偶数的数组。

举个例子看一下

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 创建</title>
</head>
<body>
  <canvas
    id="canvas"
    width="500" 
    height="500" 
    style="box-shadow: 0px 0px 5px #ccc; border-radius: 8px;">
    当前浏览器不支持canvas元素,请升级或更换浏览器!
  </canvas>
  <script>
    const canvas = document.getElementById('canvas'); // 获取Canvas
    const ctx = canvas.getContext('2d'); // 获取绘制上下文
    ctx.strokeStyle = "#f00" // 描边样式设置为红色
    ctx.lineWidth = 5

    // 绘制一条虚线
    ctx.setLineDash([5, 10, 20]);
    console.log(ctx.getLineDash()); // [5, 10, 20, 5, 10, 20]
    ctx.beginPath();
    ctx.moveTo(0,100);
    ctx.lineTo(500, 100);
    ctx.stroke();

    // 再绘制一条虚线
    ctx.setLineDash([5, 10, 20, 40]);
    console.log(ctx.getLineDash()); // [5, 10, 20, 40]
    ctx.beginPath();
    ctx.moveTo(0,200);
    ctx.lineTo(500, 200);
    ctx.stroke();

  </script>
</body>
</html>

效果如下:

image.png

在上图中我们发现,设置的虚线数组为:[5, 10, 20],但打印出来的却是:[5, 10, 20, 5, 10, 20],这是因为 getLineDash 返回虚线的长度为非负偶数的数组。所以如果传参长度为奇数,例如:ctx.setLineDash([5, 10, 20])时,setLineDash 会复制一份数组补全为偶数,等同于我们设置的是:ctx.setLineDash([5, 10, 20, 5, 10, 20])。

lineDashOffset

lineDashOffset 设置虚线样式的起始偏移量。例如:15

举个例子看一下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 创建</title>
</head>
<body>
  <canvas
    id="canvas"
    width="500" 
    height="500" 
    style="box-shadow: 0px 0px 5px #ccc; border-radius: 8px;">
    当前浏览器不支持canvas元素,请升级或更换浏览器!
  </canvas>
  <script>
    const canvas = document.getElementById('canvas'); // 获取Canvas
    const ctx = canvas.getContext('2d'); // 获取绘制上下文
    ctx.strokeStyle = "#f00" // 描边样式设置为红色
    ctx.lineWidth = 5

    // 绘制一条虚线
    ctx.setLineDash([5, 10, 20, 40]);
    console.log(ctx.getLineDash()); // [5, 10, 20, 40]
    ctx.beginPath();
    ctx.moveTo(0,100);
    ctx.lineTo(400, 100);
    ctx.stroke();
    
    ctx.setLineDash([5, 10, 20, 40]);
    ctx.lineDashOffset = 15;
    ctx.beginPath();
    ctx.moveTo(0,300);
    ctx.lineTo(400, 300);
    ctx.stroke();

  </script>
</body>
</html>

效果如下:

image.png

如图所示,虚线的总长度没有变化,但起始点向左位移了15个像素。

三角形

我们知道了直线的绘制以后,三角形的绘制也就显得格外简单,在上面的例子中其实我们已经绘制了两条直线连接在一起,那么三条直线收尾连接在一起就是我们的三角形了。举个例子:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>canvas - 三角形</title>
</head>
<body>
  <canvas
    id="canvas"
    width="500" 
    height="500" 
    style="box-shadow: 0px 0px 5px #ccc; border-radius: 8px;">
    当前浏览器不支持canvas元素,请升级或更换浏览器!
  </canvas>
  <script>
    const canvas = document.getElementById('canvas'); // 获取Canvas
    const ctx = canvas.getContext('2d'); // 获取绘制上下文
    ctx.strokeStyle = "#f00" // 描边样式设置为红色
    ctx.fillStyle = "#00f" // 填充样式设置为蓝色
    ctx.lineWidth = 5

    // 绘制一个三角形
    ctx.moveTo(50, 100) 
    ctx.lineTo(50, 400)
    ctx.lineTo(400, 400)
    ctx.lineTo(50, 100) 
    ctx.stroke();

    // 如果是填充一个三角形,则只需两条直线就行,它会默认闭合。
    ctx.beginPath()
    ctx.moveTo(200, 200) 
    ctx.lineTo(400, 200)
    ctx.lineTo(400, 370)
    ctx.fill();

  </script>
</body>
</html>

效果如下:

image.png

直线能绘制三角形那么同样的也就能绘制四边形、五边形、六边形......等等多边形。但直线也有不能绘制的东西,比如圆、曲线等。

因此Canvas还提供了一些绘制基本形状的API,具体有哪些我们下一遍文章再仔细说。

下一篇:PixiJs学前篇(二):Canvas基础【中篇】