眨个眼就学会了 Pixi.js

本文简介

带尬猴,我是德育处主任

当今的Web开发中,图形和动画已经成为了吸引用户注意力的重要手段之一。而 Pixi.js 作为一款高效、易用的2D渲染引擎,已经成为了许多开发者的首选~~(我吹的)~~。本文将为工友们介绍PixiJS的基础知识和使用方法,希望可以和工友们**快速光速入门**,掌握 Pixi.js 的用法。

实际工作中我还没有用上 Pixi.js,本文只是记录我的学习过程。将我认为入门时需要掌握的知识点记录下来。所以,你们懂的,太难的问题我回答不上,或者我会用拆特鸡皮蹄敷衍你。

环境搭建

本文将使用原生三件套的方式讲解如何使用 Pixi.js,你可以根据自己的需求搭建环境。

我使用 VS Code 开发,并在 VS Code 安装了 Live Server插件[2] 方便启动本地服务。

创建好项目后就需要安装 Pixi.js,常用的方式有 CDNNPM,选其中一种就行。

本文使用 Pixi.js 7.2 版本

CDN

本文为了和各位工友一起快速上手 Pixi.js ,所以会使用 CDN 的方式引入 Pixi.js

<script src="https://pixijs.download/release/pixi.js"></script>
复制代码

在实际项目开发中,你最好还是将 Pixi.js 保存到你的项目中再引入。

根据你的项目需求选择对应的 Pixi.js 版本:🔗 Pixi.js 历史版本下载地址[3]

NPM

工作中很多项目都会使用脚手架的方式进行开发,通常也会使用 npm 的方式下载依赖包。Pixi.js 也提供了这种方式。

npm i pixi.js
复制代码

下载好 Pixi.js 后,在需要用到 Pixi.js 的页面中引入即可。

import * as PIXI from 'pixi.js'
复制代码

其他依赖包

在创建一些特殊图形时你可以还需要使用到 @pixi/graphics-extras

CDN

<script src="https://cdn.jsdelivr.net/npm/@pixi/graphics-extras@7.x/dist/graphics-extras.min.js"></script>
复制代码

NPM

npm install @pixi/graphics-extras
复制代码

这是 @pixi/graphics-extras 的npm地址:www.npmjs.com/package/\@pi…[4]

起步

首先要做的是使用 Pixi.js 创建一个画布,并将该画布添加到页面中。

创建画布

分2步走:

  1. 使用 Pixi.js 创建画布

  2. 将画布添加到页面中

7149d0e7e687ab7fbbcfe606a6b54bd5.jpeg
01.png
<script src="https://pixijs.download/release/pixi.js"></script>
<script>
  // 1、创建 pixi画布
  let app = new PIXI.Application()

  // 2、将画布添加到页面中
  document.body.appendChild(app.view)
</script>
复制代码

如果你使用 npm 的方式安装 Pixi.js 就需要用下面这种写法。

import * as PIXI from 'pixi.js' // 引入 Pixi.js

// 1、创建 pixi画布
let app = new PIXI.Application()

// 2、将画布添加到页面中
document.body.appendChild(app.view)
复制代码

前面这两个例子都是将画布添加到页面,你也可以根据需求将画布添加到指定元素里。

<div id="d1" style="margin: 100px; border: 1px solid red;"></div>

<script src="https://pixijs.download/release/pixi.js"></script>
<script>
  // 创建 pixi画布
  let app = new PIXI.Application()

  // 找到id为d1的元素
  let d1 = document.getElementById('d1')
  // 将画布添加到d1元素里
  d1.appendChild(app.view)
</script>
复制代码

设置画布宽高

Pixi.js 默认创建出来的画布宽高是 800px * 600px

你可以在使用 Pixi.js 创建画布的时候设置好画布的宽高。

// 创建画布时设置宽高
let app = new PIXI.Application({
  width: 640,
  height: 360
})

// 将画布添加到页面里
document.body.appendChild(app.view)
复制代码

设置画布背景色

细心的工友可能已经发现,Pixi.js 创建出来的画布背景默认是黑色的。你可以在创建画布时手动设置背景色。

e2c68aba33254232056190bdab8db0f7.jpeg
02.png
// 省略部分代码...

let app = new PIXI.Application({
  backgroundColor: 'pink'
})

document.body.appendChild(app.view)
复制代码

backgroundColor 接收一个颜色值,除了像上面这样写一个颜色关键词,还可以传入 rgb、十六进制等表示颜色的值。比如:

  • backgroundColor: 'rgb(100, 0, 100)'

  • backgroundColor: '#1182af'

  • backgroundColor: 0x1182af

自动调整大小

如果希望画布跟随父元素大小改变,可以设置 resizeTo

比如,我想让画布跟随浏览器窗口大小变化,可以这样设置。

let app = new PIXI.Application({
  resizeTo: window
})
复制代码

此时可能你会发现画布的宽高好像导致浏览器产生了水平和垂直的滚动条,可以通过 CSS 解决这个问题。

html, body {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
}

canvas {
  position: fixed;
  top: 0;
  left: 0;
}
复制代码

销毁画布

使用 destroy() 方法可以销毁画布。

outside_default.png
25.gif
<button onclick="">删除画布</button>

<script>
// 省略创建画布的代码

// 删除画布
function delCanvas() {
  app.destroy()
}
</script>
复制代码

细心的你可能发现了,上面的操作只是清除了画布,<canvas> 元素还是留在页面上的。

如果你想把 <canvas> 元素也清掉,可以使用 app.destroy() 时传入 true

outside_default.png
26.gif
// 省略部分代码

function delCanvas() {
  app.destroy(true)
}
复制代码

基础图形

创建好画布后,就开始学习一下如何创建基础图形。这也是我认为入门阶段最重要的内容。

先从最简单的图形说起,清楚 Pixi.js 可以创建哪些图形后,后面的章节再讲解如何设置样式。

Pixi.js 创建图形需要用到 GraphicsGraphics 里包含了很多基础图形。

创建图形需要做以下几步:

  1. 实例化 Graphics 类。

  2. 设置填充或描边颜色。

  3. 创建图形。

  4. 执行绘制操作。

注意:以上几个步骤一定要按顺序做,一定要先设置颜色再创建图形,不然图形就可能没颜色或者使用上下文的颜色。

矩形 (drawRect)

Pixi.js 提供了好几种矩形,最基础的是 drawRect。

语法

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

这语法和 原生Canvasrect() 方法很像。

  • xy 是矩形左上角坐标的位置,这个位置是相对于画布而言的。

  • widthheight 是矩形的宽高。

看个例子:

ceb832a133394b04d504b73c2e0d41ac.jpeg
03.png
// 创建画布
let app = new PIXI.Application({
  width: 300,
  height: 300
})

// 将画布添加到页面
document.body.appendChild(app.view)

// 创建图形类
const graphics = new PIXI.Graphics()
// 设置填充颜色 beginFill(颜色, 不透明度)
graphics.beginFill(0xffd900, 1)
// 创建图形(矩形)
graphics.drawRect(50, 50, 200, 100)
// 绘制操作
graphics.endFill()

// 将绘制好的图形添加到画布中
app.stage.addChild(graphics)
复制代码

圆角矩形 (drawRoundedRect)

了解了基础的矩形怎么创建之后,接下来的图形都比较容易掌握了。

创建圆角矩形可以使用 drawRoundedRect() 方法,这个方法比普通矩形多一个圆角参数。

语法

drawRoundedRect(x, y, width, height, radius)
复制代码
  • xywidthheight 都跟 矩形Rect() 一样。

  • radius 参数可以控制四个角的圆角半径。

eb31dc4106efb890c7bffc4cb61169d7.jpeg
04.png
// 创建画布
let app = new PIXI.Application({
width: 300,
height: 300
})

// 将画布添加到页面
document.body.appendChild(app.view)

// 创建图形类
const graphics = new PIXI.Graphics()
// 设置填充颜色 beginFill(颜色, 不透明度)
graphics.beginFill(0xffd900, 1)
// 创建圆角矩形
graphics.drawRoundedRect(50, 50, 200, 100, 10) // 最后一个参数是圆角半径
// 绘制操作
graphics.endFill()

// 将绘制好的图形添加到画布中
app.stage.addChild(graphics)
复制代码

其实在用 drawRoundedRect 时,你不传最后一个参数 radius 它也不会怪你的,因为它本身有默认值嘛。

2af147fd3812c2cb0cca14d0aa476521.jpeg
05.png
// 省略部分代码...

graphics.drawRoundedRect(50, 50, 200, 100)
复制代码

倒角矩形 (drawChamferRect)

我不知道把 drawChamferRect 翻译成“倒角矩形”正不正确,意思就是将举行的4个角切掉磨平。

drawChamferRect() 并不在 Pixi.js 的基础包里,你**需要另外下载 @pixi/graphics-extras**,CDNNPM 的地址在前面的《其他依赖包》章节。

drawChamferRect 语法

drawChamferRect(x, y, width, height, chamfer)
复制代码

chamfer 参数就是倒角的切口,数值越大切口越大。

<!-- 引入 pixi -->
<script src="https://pixijs.download/release/pixi.js"></script>
<!-- 引入 graphics-extras,特殊图形的包 --->
<script src="https://cdn.jsdelivr.net/npm/@pixi/graphics-extras@7.x/dist/graphics-extras.min.js"></script>

<script>
  // 创建画布
  let app = new PIXI.Application({
    width: 300,
    height: 300
  })

  // 将画布添加到页面
  document.body.appendChild(app.view)

  // 创建图形类
  const graphics = new PIXI.Graphics()
  // 设置填充颜色 beginFill(颜色, 不透明度)
  graphics.beginFill(0xffd900, 1)
  // 创建倒角矩形
  graphics.drawChamferRect(50, 50, 200, 100, 10) // 最后一个参数控制倒角切口大小
  // 绘制操作
  graphics.endFill()

  // 将绘制好的图形添加到画布中
  app.stage.addChild(graphics)
</script>
复制代码

和圆角矩形不同,使用 drawChamferRect() 时一定要传入最后一个参数。

倒圆角矩形 (drawFilletRect)

同样的,我也不清楚用 “倒圆角矩形” 描述 drawFilletRect 这个方法有没有问题,详情看看效果图。

**要使用 drawFilletRect() 也需要引入 @pixi/graphics-extras**。

语法

DrawFilletRect(x,y,width,height,fillet)
复制代码

参数 fillet 表示圆角半径,它属于 圆角矩形 drawRoundedRect 的升级版,因为 fillet 可以接收负数。

fillet 是正数是,它画出来的图像和普通圆角矩形差不多;当 fillet 为负数时,圆角就会向内凹进去。

f0ee649badb494f9c4e325b824ec7a36.jpeg
06.png
<script src="../js/pixi.js"></script>
<script src="../js/graphics-extras.js"></script>
<script>
  // 创建画布
  let app = new PIXI.Application({
    width: 300,
    height: 300
  })

  // 将画布添加到页面
  document.body.appendChild(app.view)

  // 创建图形类
  const graphics = new PIXI.Graphics()
  // 设置填充颜色 beginFill(颜色, 不透明度)
  graphics.beginFill(0xffd900, 1)
  // 创建倒圆角矩形
  graphics.drawFilletRect(50, 50, 200, 100, -20) // 最后一个参数为负数时,圆角向内凹进去
  // 绘制操作
  graphics.endFill()

  // 将绘制好的图形添加到画布中
  app.stage.addChild(graphics)
</script>
复制代码

圆形 (drawCircle)

圆形是 Pixi.js 的基础图形,并不需要额外的引入 @pixi/graphics-extras.js

创建圆形的方法叫 drawCircle(),语法如下:

drawCircle(x, y, radius)
复制代码
  • xy 是圆心的位置。

  • radius 是圆的半径。

需要注意的是 xy ,它和矩形不同,矩形的 xy 是定义矩形左上角的位置。

433c6c168ab97d5d3b2fe02978b00515.jpeg
07.png
// 创建画布
let app = new PIXI.Application({
  width: 300,
  height: 300
})

// 将画布添加到页面
document.body.appendChild(app.view)

// 创建图形类
const graphics = new PIXI.Graphics()
// 设置填充颜色 beginFill(颜色, 不透明度)
graphics.beginFill(0xffd900, 1)
// 创建圆形
graphics.drawCircle(100, 100, 50) // x, y, radius
// 绘制操作
graphics.endFill()

// 将绘制好的图形添加到画布中
app.stage.addChild(graphics)
复制代码

椭圆 (drawEllipse)

使用 drawEllipse() 方法可以绘制椭圆,该方法是 Pixi.js 提供的,无需额外引入 @pixi/graphics-extras.js

语法

drawEllipse(x, y, width, height)
复制代码
  • xy 是椭圆的圆心位置。

  • width 是椭圆的宽度,height 是椭圆的高度。

需要注意,在 Pixi.js 中,椭圆是用宽高来表示的。其他 Canvas 库的椭圆宽高可能会用 xy 方向的半径来表示,比如 `Fabric.js` 的椭圆[5] ,这点大家需要注意一下。

801c309271b56d8e71772bcf2a4ea126.jpeg
08.png
// 创建画布
let app = new PIXI.Application({
  width: 300,
  height: 300
})

// 将画布添加到页面
document.body.appendChild(app.view)

// 创建图形类
const graphics = new PIXI.Graphics()
// 设置填充颜色 beginFill(颜色, 不透明度)
graphics.beginFill(0xffd900, 1)
// 创建椭圆
graphics.drawEllipse(100, 50, 100, 50) // x, y, width, height
// 绘制操作
graphics.endFill()

// 将绘制好的图形添加到画布中
app.stage.addChild(graphics)
复制代码

多边形 (drawPolygon)

使用 drawPolygon() 方法可以绘制多边形,该方法接收1个参数,这个参数是一个数值型数组,用来表示多边形顶点坐标。

drawPolygon 方法会自动将起始点和结束点连接起来,形成一个封闭的图形。

语法

drawPolygon(…path)

// 这是我书写习惯
drawPolygon([
	x1, y1,
	x2, y2,
	x3, y3,
	......
])
复制代码
901a574900c7945164f997e2d80ae818.jpeg
09.png
// 创建画布
let app = new PIXI.Application({
  width: 300,
  height: 300
})

// 将画布添加到页面
document.body.appendChild(app.view)

// 创建图形类
const graphics = new PIXI.Graphics()
// 设置填充颜色 beginFill(颜色, 不透明度)
graphics.beginFill(0xffd900, 1)

// 路径,两两一组代表一个坐标
const path = [
  30, 30,
  100, 50,
  100, 180,
  30, 200
]

// 创建多边形
graphics.drawPolygon(path)
// 绘制操作
graphics.endFill()

// 将绘制好的图形添加到画布中
app.stage.addChild(graphics)
复制代码

路径坐标是两两一组的,二维世界里一个点用x和y两个坐标来描述。

上面是我的书写习惯,比较容易看出点的位置和数量。

正多边形 (drawRegularPolygon)

正方形、等边三角形都属于正多边形。

Pixi.js 里,使用 drawRegularPolygon() 方法可以绘制正多边形,但前提是**要引入 @pixi/graphics-extras.js**。

语法

drawRegularPolygon(x, y, radius, sides, rotation)
复制代码
  • xy 是多边形的中心点坐标。

  • radius 是多边形的半径,也就是中心点到各个点的距离。

  • sides 是多边形的边数,最小值是3。

  • rotation 是多边形的旋转弧度,默认值是0。

需要注意的是,rotation 是以弧度为单位的,如果想直观的表达角度,可以用下面这条公式

角度 * Math.PI / 180
复制代码

举个例子

3435ab1e81b84b8a3cbddf0006f33cc0.jpeg
10.png
<!-- 引入 pixi -->
<script src="https://pixijs.download/release/pixi.js"></script>
<!-- 引入 graphics-extras,特殊图形的包 --->
<script src="https://cdn.jsdelivr.net/npm/@pixi/graphics-extras@7.x/dist/graphics-extras.min.js"></script>

<script>
  // 创建画布
  let app = new PIXI.Application({
    width: 300,
    height: 300
  })

  // 将画布添加到页面
  document.body.appendChild(app.view)

  // 创建图形类
  const graphics = new PIXI.Graphics()
  // 设置填充颜色 beginFill(颜色, 不透明度)
  graphics.beginFill(0xffd900, 1)

  // 创建正多边形
  // x, y, 半径(图形尺寸), 边数, 旋转弧度
  graphics.drawRegularPolygon(40, 40, 30, 6, 10 * Math.PI / 2)
  // 绘制操作
  graphics.endFill()

  // 将绘制好的图形添加到画布中
  app.stage.addChild(graphics)

</script>
复制代码

圆角正多边形 (drawRoundedPolygon)

Pixi.js 使用 drawRoundedPolygon() 方法绘制圆角,使用该方法之前**需要引入 @pixi/graphics-extras.js**。

语法

drawRoundedPolygon(x, y, radius, sides, corner, rotation)
复制代码

相比起正多边形,圆角正多边形多了个圆角,所以需要传入的参数也会比正多边形多一个圆角半径

  • xy 是圆角正多边形的中心点。

  • radius 是圆角正多边形的半径(中心点到各个顶点的距离)。

  • sides 是边的数量。

  • corner 是每个角的圆角半径,这个参数是必传的!

  • rotation 是旋转弧度。

举个例子

d784253479221ae557d57cacf802fbcd.jpeg
11.png
<!-- 引入 pixi -->
<script src="https://pixijs.download/release/pixi.js"></script>
<!-- 引入 graphics-extras,特殊图形的包 --->
<script src="https://cdn.jsdelivr.net/npm/@pixi/graphics-extras@7.x/dist/graphics-extras.min.js"></script>

<script>
  // 创建画布
  let app = new PIXI.Application({
    width: 300,
    height: 300
  })

  // 将画布添加到页面
  document.body.appendChild(app.view)

  // 创建图形类
  const graphics = new PIXI.Graphics()
  // 设置填充颜色 beginFill(颜色, 不透明度)
  graphics.beginFill(0xffd900, 1)

  // 创建圆角正多边形
  // x, y, 半径(图形尺寸), 边数, 圆角, 旋转弧度
  graphics.drawRoundedPolygon(100, 100, 80, 6, 10, 10 * Math.PI / 180)
  // 绘制操作
  graphics.endFill()

  // 将绘制好的图形添加到画布中
  app.stage.addChild(graphics)

</script>
复制代码

环形 (drawTorus)

环形也是特殊图形,同样 **需要引入 @pixi/graphics-extras.js**。

创建环形的方法是 drawTorus() 。

语法

drawTorus(x, y, innerRadius, outerRadius, startArc, endArc)
复制代码
  • xy 是环形的圆心坐标。

  • innerRadius 是内圆半径。

  • outerRadius 是外圆半径。

  • startArc 环形开始位置,默认是0,单位是弧度。该参数可以不填。

  • endArc 环形结束位置,默认是 Math.PI * 2单位是弧度。该参数可以不填。

如果不填写 startArcendArc ,画出来的是一个没缺口的环形。

62df95646dcbe8a03bad2422623d5eaa.jpeg
12.png

经过前面几个图形的锻炼,本例开始就省略一些套路式的代码了。

// 创建画布
let app = new PIXI.Application({
  width: 300,
  height: 300
})

// 将画布添加到页面
document.body.appendChild(app.view)

// 创建图形类
const graphics = new PIXI.Graphics()
// 设置填充颜色 beginFill(颜色, 不透明度)
graphics.beginFill(0xffd900, 1)

// 创建环形,只传入4个参数 x, y, 内圆半径, 外圆半径
graphics.drawTorus(100, 100, 30, 60)
// 绘制操作
graphics.endFill()

// 将绘制好的图形添加到画布中
app.stage.addChild(graphics)
复制代码

如果把开始位置和结束位置也设置一下,就有可能得到一个“不闭合”的环形

af8053a917de4a5125e22330cd89960d.jpeg
13.png
// 创建环形
graphics.drawTorus(100, 100, 30, 60, 0.5, 5.5)
复制代码

星形 (drawStar)

星形 drawStar() 也是特殊图形, **需要引入 @pixi/graphics-extras.js**。

语法

drawStar(x, y, points, radius, innerRadius, rotation)
复制代码
  • xy 是星形的中心坐标。

  • points 代表点数,也就是星星有多少个角是由这个参数控制的,这个值必须大于1。

绘制图形 (drawShape)

从官方文档的描述来看,drawShape() 方法是可以绘制任何图形的。

Draw any shape.

2a5a78937cd924614d0f0cf02ba3347c.jpeg
14.png
// 省略部分代码......

// 创建图形类
const graphics = new PIXI.Graphics()
// 设置填充颜色 beginFill(颜色, 不透明度)
graphics.beginFill(0xffd900, 1)

// 创建一个多边形对象
const path2 = new PIXI.Polygon([
  10, 10, // 第一个点的坐标
  50, 100, // 第二个点的坐标
  100, 10 // 第三个点的坐标
])

graphics.drawShape(path2)
// 绘制操作
graphics.endFill()

// 将绘制好的图形添加到画布中
app.stage.addChild(graphics)
复制代码

在这个例子中我使用 PIXI.Polygon 建立了3个坐标点的形状,然后把结果丢进 drawShape 创建图形。

折线 (moveTo 和 lineTo)

Pixi.js 里使用 moveTo()lineTo()方法绘制折线,和 原生Canvas 很像。

  • moveTo() 传入的是起始点坐标。

  • lineTo() 可以存在多个,每个 lineTo() 里都可以传入一个坐标点,表示折线的顶点。

bc3c8984a4de6175764ed306802ac87d.jpeg
15.png
// 省略部分代码......

// 创建图形类
const graphics = new PIXI.Graphics()
// 设置描边颜色 beginFill(颜色, 不透明度)
graphics.lineStyle(4, 0xffd900, 1)

// 创建折线
graphics.moveTo(10, 40) // 起始点
graphics.lineTo(40, 20) // 经过的点
graphics.lineTo(50, 80)
graphics.lineTo(100, 70)

// 将绘制好的图形添加到画布中
app.stage.addChild(graphics)
复制代码

闭合折线

在折线的基础上,还可以在最后加上一个 closePath() 方法闭合折线。这就会形成一个封闭图形。

closePath() 方法会将折线的起点和终点连接起来。

8620bc21607aa9d04433408ec9d5f851.jpeg
16.png
// 省略部分代码......

// 创建图形类
const graphics = new PIXI.Graphics()

// 设置秒变颜色
graphics.lineStyle(4, 0xffd900, 1)

graphics.moveTo(10, 40) // 起始点
graphics.lineTo(40, 20) // 经过的点
graphics.lineTo(50, 80)
graphics.lineTo(100, 70)

graphics.closePath() // 闭合
复制代码

圆弧 (arc)

创建圆弧使用的方法是 arc()

语法

arc(cx, cy, radius, startAngle, endAngle, anticlockwise)
复制代码
  • cxcy 是圆心坐标。

  • radius 是圆弧半径。

  • startAngle 圆弧的开始角度(以弧度表示)。

  • endAngle 圆弧的结束角度(以弧度表示)。

  • anticlockwise 绘制方向,true 表示逆时针方向绘制,false 表示顺时针。默认值为 false

60aaa76168742955e66395bba2fe25be.jpeg
17.png
// 省略部分代码......

// 创建图形类
const graphics = new PIXI.Graphics()

// 设置线的颜色
graphics.lineStyle(4, 0xffd900, 1)

// 创建圆弧
graphics.arc(100, 100, 50, Math.PI, 2.3 * Math.PI)

// 将绘制好的图形添加到画布中
app.stage.addChild(graphics)
复制代码

圆弧(arcTo)

你没看错,创建圆弧除了 arc() 方法外,还有 arcTo() 方法。

arcTo()Pixi.js 中的一个图形绘制函数,用于绘制从当前点到指定点之间的弧线。

Pixi.jsarcTo() 方法其实和 原生CanvasarcTo() 用法差不多,在使用之前害需要 moveTo 配合。

关于 CanvasarcTo() 方法我在 《Canvas 从入门到劝朋友放弃(图解版)》[6] 有讲到,有兴趣的工友可以去看看。

Pixi.jsarcTo() 语法

arcTo(x1, y1, x2, y2, radius)
复制代码
  • x1y1 是弧线的起始点坐标。

  • x2y2 是弧线的终点坐标。

  • radius 是弧线的半径。

74b73590a44a28c5991dc2e8139f8e17.jpeg
18.png
// 省略部分代码......

// 创建图形类
const graphics = new PIXI.Graphics()

// 创建折线
graphics.lineStyle(4, 0xffd900, 1)
graphics.moveTo(40, 40) // 先确定起始点
graphics.arcTo(120, 40, 120, 120, 80)
graphics.endFill()

// 将绘制好的图形添加到画布中
app.stage.addChild(graphics)
复制代码

贝塞尔曲线

贝塞尔曲线是一种数学曲线,可以用于绘制复杂的图形。在 Pixi.js 中,bezierCurveTo 方法可以用来绘制二次或三次贝塞尔曲线。

二次贝塞尔曲线有3个关键坐标点:起始点、控制点、结束点。

三次贝塞尔曲线比二次贝塞尔曲线多1个控制点,理解了二次贝塞尔曲线就能理解三次贝塞尔曲线。

84ed32b5a3bc785aa2717bd071625933.jpeg
19.png

我用一张图简单讲解一下二次贝塞尔曲线。

moveTo(50, 100) 是起始点,(100, 50)(150, 100) 是贝塞尔曲线的控制点。

将这3个坐标连起来,也就是上图所示的2条灰色的线。

在这两条灰色的线上,各自平均画了4个点,然后按顺序把这些点连起来,如上图所示。

最后,将第一条灰线和红线点交点、红线和黄线点交点、黄线和蓝线点交点、蓝线和绿线点交点以及绿线和最后一条灰线点交点连接起来。形成一条新的曲线。这就是贝塞尔曲线(下图的紫线)。

140e39bed7f8e02b220447ceacfe8991.jpeg
20.png

因为我画的线比较少,所以形成的曲线还是有棱角。如果希望曲线更圆润,你需要画更多的线形成更多的交点。

说了这么多,回到 Pixi.js ,看看使用 Pixi.js 怎么画贝塞尔曲线。

二次贝塞尔曲线

使用 quadraticCurveTo() 方法可以绘制二次贝塞尔曲线。

语法

quadraticCurveTo(cpX, cpY, toX, toY)
复制代码
  • 在使用 quadraticCurveTo() 前,需要使用 moveTo() 定义曲线的起点。

  • quadraticCurveTo()cpXcpY 是第一个控制点。

  • toXtoY 是第二个控制点。

02e5e0accaa1c9df4475f404298789db.jpeg
21.png
// 创建图形类
const graphics = new PIXI.Graphics()

// 创建折线
graphics.lineStyle(4, 0xffd900, 1)

graphics.moveTo(50, 100)
graphics.quadraticCurveTo(100, 50, 150, 100) // 二次贝塞尔曲线

// 将绘制好的图形添加到画布中
app.stage.addChild(graphics)
复制代码

三次贝塞尔曲线

Pixi.js 中,绘制三次贝塞尔曲线需要使用另一个方法:bezierCurveTo()

语法

bezierCurveTo(cpX, cpY, cpX2, cpY2, toX, toY)
复制代码

绘制三次贝塞尔曲线同样需要先使用 moveTo() 配合。

30edc087c1069cbe2cc6a45aee13e79e.jpeg
22.png
// 创建图形类
const graphics = new PIXI.Graphics()

// 创建折线
graphics.lineStyle(4, 0xffd900, 1)

graphics.moveTo(50, 100)
graphics.bezierCurveTo(100, 50, 150, 100, 200, 100) // 三次贝塞尔曲线

// 将绘制好的图形添加到画布中
app.stage.addChild(graphics)
复制代码

文本 Text

使用 Pixi.js 渲染文本非常简单,只需用到 Text() 方法即可。

语法

new PIXI.Text(text, style, canvas)
复制代码

在本小节我们只需知道 new PIXI.Text('文本内容') 这样用即可,样式部分我放在后面讲解。

c6c6b79b46cfa17f7b6152023f4b88ed.jpeg
23.png
// 创建画布
let app = new PIXI.Application({
  width: 300,
  height: 300,
  backgroundColor: 0xf0f0f0
})

// 将画布添加到页面
document.body.appendChild(app.view)

const text = new PIXI.Text('雷猴')

// 将文本添加到画布中
app.stage.addChild(text)
复制代码

使用 new PIXI.Text() 创建的文字默认是黑色,所以在本例中我把画布背景色设置成浅灰色,方便观察文字。

图片

Pixi.js 里,加载图片资源需要做以下操作:

  1. 加载图片纹理

  2. 将纹理放入“精灵”对象

  3. 将“精灵”添加到画布中

772cfa6af128c70d887a45f3a8fd1cfd.jpeg
24.png
// 创建画布
let app = new PIXI.Application()

// 将画布添加到页面
document.body.appendChild(app.view)

// 加载图片
const texture = PIXI.Texture.from('./dinosaur.png')
// 将纹理放在“精灵“的图形对象上
const sprite = new PIXI.Sprite(texture)
// 将精灵添加到画布中
app.stage.addChild(sprite)
复制代码

使用 PIXI.Texture 方法加载图片纹理,但这个方法前面是不需要 new 的,这点要注意!

PIXI.Texture.from() 除了加载本地图片,还能加载网络图片。

const texture = PIXI.Texture.from('https://pixijs.io/examples/examples/assets/bunny.png')
复制代码

常用样式配置

终于来到样式讲解部分了。

前面讲解的图形、文本、图片都是 Pixi.js 的基础元素,他们都支持样式设置。

基础图形样式

图形的样式我用矩形来举例。基础图形的宽高、半径之类的使用方法在前面已经讲过了,这里不再重复。

填充色

使用 beginFill() 设置填充色。

使用 endFill() 可以结束上一个 beginFill() 方法定义的填充样式。如果没有调用endFill()方法,则填充样式会一直应用到后续的所有形状上,直到定义新的填充样式。

在绘制图形时,通常需要使用beginFill()方法定义填充样式,然后使用drawRect()drawCircle()等方法绘制形状,最后调用endFill()方法结束填充。

beginFill() 语法

beginFill(color, alpha)
复制代码
  • color: 要填充的颜色,默认值是0,表示黑色。这个参数有几种情况,我会详细说明。

  • alpha: 透明通道。默认值是1,表示完全不透明。0 表示完全透明。0-1之间的值表示不同程度的半透明。

颜色关键字

举个例子(颜色关键字)

bff68f79d87b533442e212cd32cd909a.jpeg
27.png
// 省略部分代码......

// 创建图形类
const graphics = new PIXI.Graphics()

// 设置填充颜色 beginFill
graphics.beginFill('hotpink')

// 创建图形(矩形)
graphics.drawRect(50, 50, 200, 100)

// 绘制操作
graphics.endFill()

// 将绘制好的图形添加到画布中
app.stage.addChild(graphics)
复制代码

在这个例子中,我传入的是 'hotpink' 亮粉色。使用颜色关键字时,需要把关键字用单引号或者双引号括起来。

十六进制

接下来看另一种情况:十六进制颜色表示法。

3a6f12ab3e35098b563eb40f001349f4.jpeg
28.png
// 省略部分代码......

// 十六进制颜色表示法
graphics.beginFill('#0fff00')

// 或者
graphics.beginFill(0x0fff00)
复制代码

上面两种写法都是十六进制的颜色表示法,学过 CSS 的工友对这种颜色表示方法应该不陌生。

需要注意的是,如果你使用 # 开头的方式,需要套上单引号或者双引号,把它变成一个字符串。

如果不想套引号,就是用 0x 开头的方式。

数值

接下来看看只传入一个数字的情况。

beginFill(color) 里的 color 参数默认值是 0。它表示黑色。

Pixi.js 会将你传入的十进制数转成十六进制。也就是说,0 会变成 0x000000

我们将上一个例子中的 0x0fff00 绿色转成十进制再传入 beginFill() 里,出来的效果是一样的。

8cb9c5f07b7a13d67719e9c38d996a1c.jpeg
29.png

我用手算法计算了一下,0x0fff00 转成十进制后是 1048320

// 省略部分代码......

graphics.beginFill(1048320)
复制代码

现在应该知道为什么 beginFill() 默认是黑色了吧。

这种传单个十进制数值的方法我们很少用。

不透明度

不透明度的配置方法就是给 beginFill() 传入第二个参数,这个参数的取值范围是 0 ~ 1 。默认值是1。

graphics.beginFill('hotpink', 0.8)
复制代码

这个太简单了,我就不贴图了,你们在自己电脑试试吧。

边框样式

lineStyle()Pixi.js 的描边方法。

语法

lineStyle(width, color, alpha, alignment, native)
复制代码
  • width: 描边宽度,默认值是 0

  • color: 描边颜色,默认值是 0

  • alpha: 描边的不透明度,默认值是 1

  • alignment: 描边的对齐方式,取值:0 = inner 内部, 0.5 = middle 中间, 1 = outer 外部,默认值是 0.5

  • native: 表示是否使用 LINES 而不是 TRIANGLE_STRIP 来绘制线条。默认值是 false

我们通常只用到前3个参数,甚至只是用到前2个参数。

cf59eb54acf54d005340e123f6669966.jpeg
30.png
const app = new PIXI.Application({
  width: 300,
  height: 300
})

document.body.appendChild(app.view)

const graphics = new PIXI.Graphics()

// 设置描边宽度和颜色
graphics.lineStyle(2, 0xff0000)
graphics.drawRect(50, 50, 100, 100)

app.stage.addChild(graphics)
复制代码

文本样式

前面提到创建文本使用 new PIXI.Text() 方法,第一个参数是文本内容,第二个参数是样式对象。

常用配置

常见的配置有字体、字号、填充色、描边色。

74cb2e25cfb5c86048ecd500a532b6fe.jpeg
31.png
// 省略部分代码......

const text = new PIXI.Text(
  "雷猴",
  {
    fontFamily: 'Arial', // 字体
    fontSize: 36, // 字号
    fill: 'yellow', // 填充色
    stroke: 'red', // 描边颜色
    strokeThickness: 2 // 描边宽度,默认是0
  }
)

app.stage.addChild(text)
复制代码

字距

letterSpacing 属性可以设置字距。

020b764f1abfb945eb13b88bb381944a.jpeg
32.png
const text = new PIXI.Text(
  "雷猴",
  {
    fill: 'yellow', // 填充色
    letterSpacing: 20
  }
)
复制代码

文本投影

Pixi.js 里设置文字投影需要配置一堆属性,这堆属性都是以 dropShadow 开头的。

具体用法请看代码注释。

53b9b1e0ce2bd871124fe0bde5633bd7.jpeg
33.png
const text = new PIXI.Text(
  "雷猴",
  {
    fontSize: 60,
    fill: 'yellow', // 填充色
    dropShadow: true, // 开启投影
    dropShadowColor: 'red', // 投影颜色
    dropShadowBlur: 6, // 投影羽化程度(模糊度)
    dropShadowAngle: 45 * Math.PI / 180, // 投影角度
    dropShadowDistance: 10 // 投影距离
  }
)
复制代码

文本渐变填充

通过前面的例子我们已经知道设置文本的 fill 属性可以配置文本颜色,其实这个属性还可以传入一个颜色数组,它就会变成渐变填充。

841ba041f01d6f09513a34cefa9a2986.jpeg
34.png
const text = new PIXI.Text(
  "雷猴",
  {
    fontSize: 60,
    fill: ['yellow', 'red', 'purple', 'blue'], // 填充色
  }
)
复制代码

默认的渐变方向是从上往下,如果你想改成从左往右渐变,可以设置 fillGradientType 属性。

9ad17079550de577c2e952d32cdeeecf.jpeg
35.png
const text = new PIXI.Text(
  "雷猴",
  {
    fontSize: 60,
    fill: ['yellow', 'red', 'purple', 'blue'], // 填充色
    fillGradientType: PIXI.TEXT_GRADIENT.LINEAR_HORIZONTAL
  }
)
复制代码

fillGradientType 的默认值是 PIXI.TEXT_GRADIENT.LINEAR_VERTICAL ,就是让渐变从上往下走。

PIXI.TEXT_GRADIENT.LINEAR_HORIZONTAL 可以让渐变从左往右走。

PIXI.TEXT_GRADIENT.LINEAR_VERTICALPIXI.TEXT_GRADIENT.LINEAR_HORIZONTAL 都是 Pixi.js 提供的。

文本纹理

我们还可以使用图片作为文本的纹理。

操作步骤:

  1. 创建文字

  2. 加载图片

  3. 将图片设置为文本的遮罩层

cf983eb67174c9eacee3e069121af995.jpeg
36.png
const text = new PIXI.Text(
  "雷猴,带尬猴,我嗨德育处主任",
  {
    fontSize: 60,
    fontWeight: 900, // 字体重量
    fill: 0xffffff, // 必须设置非黑色的填充色
  }
)

// 加载图片
const bunny = PIXI.Sprite.from('./pexels-alexander-grey.jpg')
// 设置图片宽高
bunny.width = app.screen.width
bunny.height = app.screen.height

// 配置文字遮罩层
bunny.mask = text

// 注意!需要将遮罩层图片添加到画布中,而不是添加文字text
app.stage.addChild(bunny)
复制代码

为了方便演示,我还设置了 fontWeight 属性,让文本变得更粗。

这个例子我使用的图片是这个:

a27a630027d877b38ab0e5264e47091a.jpeg
37.jpg

图片样式

前面已经讲过图片怎么使用了,本小节讲讲图片常用的属性。

宽高

通过设置 widthheight 可以修改图片的宽高。

56bd2a5e638bc5d1e58b1dc850542265.jpeg
38.png
// 省略部分代码

// 加载图片
const texture = PIXI.Texture.from('./dinosaur.png')
// 将纹理放在“精灵“的图形对象上
const sprite = new PIXI.Sprite(texture)

// 设置精灵宽高
sprite.width = 100
sprite.height = 100

// 将精灵添加到画布中
app.stage.addChild(sprite)
复制代码

位置

通过设置 xy 可以修改图片的位置。

91b14cc09522ca3bb9c93e7d2a2087d2.jpeg
39.png
// 省略部分代码

// 加载图片
const texture = PIXI.Texture.from('./dinosaur.png')
// 将纹理放在“精灵“的图形对象上
const sprite = new PIXI.Sprite(texture)

// 设置精灵宽高
sprite.x = 100
sprite.y = 100

// 将精灵添加到画布中
app.stage.addChild(sprite)
复制代码

旋转

通过设置 rotation 属性旋转图片。

18ab5321178e4294abe15064f6211aa2.jpeg
40.png
// 省略部分代码

// 加载图片
const texture = PIXI.Texture.from('./dinosaur.png')
// 将纹理放在“精灵“的图形对象上
const sprite = new PIXI.Sprite(texture)

// 往右移动精灵
sprite.x = 100
// 旋转45度
sprite.rotation = 45 * Math.PI / 180

// 将精灵添加到画布中
app.stage.addChild(sprite)
复制代码

可见性

使用 visible 可以控制图片的可见性。

当图片的 visible 属性设置为 false 时就不可见了。

// 加载图片
const texture = PIXI.Texture.from('./dinosaur.png')
// 将纹理放在“精灵“的图形对象上
const sprite = new PIXI.Sprite(texture)

// 隐藏图片
sprite.visible = false
复制代码

透明度

通过 alpha 属性可以设置图片的不透明度,取值范围是 0 ~ 1

196775fb114eb418a963f6172f1d3d23.jpeg
41.png
// 省略部分代码

// 加载图片
const texture = PIXI.Texture.from('./dinosaur.png')
// 将纹理放在“精灵“的图形对象上
const sprite = new PIXI.Sprite(texture)

// 设置不透明度
sprite.alpha = 0.6
复制代码

滤镜

滤镜是个挺有意思的东西,滤镜可以用来增强图形的视觉效果,同时也可以用来实现各种特殊效果,例如模糊、发光等。Pixi.js中的滤镜功能十分简单易用,只需要在对象上添加相应的滤镜即可。

我拿几款滤镜出来讲解一下,其他的滤镜用法可以自行查阅文档,不难的~

模糊滤镜

使用 new PIXI.BlurFilter() 可以创建模糊滤镜。

70021f612f3f95f68d13fadd57a8e984.jpeg
42.png
// 创建画布
let app = new PIXI.Application({
  width: 300,
  height: 300
  // resizeTo: window
})

// 将画布添加到页面
document.body.appendChild(app.view)

// 加载图片
const texture = PIXI.Texture.from('./dinosaur.png')
// 将纹理放在“精灵“的图形对象上
const sprite = new PIXI.Sprite(texture)

// 模糊滤镜
const blurFilter = new PIXI.BlurFilter()
// 模糊程度
blurFilter.blur = 10

// 将模糊滤镜添加到图片精灵上
sprite.filters = [blurFilter]

// 将精灵添加到画布中
app.stage.addChild(sprite)
复制代码

细心的工友可能已经发现,添加滤镜是用数组存起来的:sprite.filters = [blurFilter]

这意味着一个元素可以同时使用多款滤镜组合。

上面的写法,其实还可以进一步简化

const blurFilter = new PIXI.BlurFilter()
blurFilter.blur = 10

// 还可以这样写
const blurFilter = new PIXI.BlurFilter(10)
复制代码

Alpha滤镜

Alpha滤镜可以设置元素的Alpha通道,也就是能设置元素的不透明度,正常的取值范围是 0 ~ 1

fd30022bd6c61a686671e12adea41ed2.jpeg
43.png
// 省略部分代码

// Alpha滤镜
const alphaFilter = new PIXI.AlphaFilter(0.5)

// 将滤镜添加到精灵上
sprite.filters = [alphaFilter]
复制代码

刚刚说了,正常取值 0 ~ 1,那不正常取值呢?

我测试了一下,如果取值超出1,元素就会出现过曝的效果。如果取值小于0,会保持透明。

1b23cc8d1491a17982ecc3482d39225a.jpeg
44.png
const alphaFilter = new PIXI.AlphaFilter(2)
复制代码

其他滤镜我就不在本文过多讲解了,有兴趣的可以自行查阅文档。

事件

Pixi.js 提供了许多交互事件,以便用户可以与场景中的元素进行交互。在 Pixi.js 中,交互事件可以是鼠标事件,也可以是触摸事件。

由于用法比较简单,我用鼠标事件举例。

鼠标点击事件

点击事件会在用户单击鼠标或触摸屏时触发,在 Pixi.js 里,点击事件叫 click

完整用法如下所示

// 创建画布
let app = new PIXI.Application({
  width: 300,
  height: 300
  // resizeTo: window
})

// 将画布添加到页面
document.body.appendChild(app.view)

// 创建矩形
const rect = new PIXI.Graphics()
rect.beginFill(0xff6600)
rect.drawRect(0, 0, 64, 64)
rect.endFill()

// 开启交互模式
rect.interactive = true
// 设置指针样式
rect.cursor = "pointer"

// 矩形的点击事件
rect.on('click', () => {
  console.log('click')
})

// 将精灵添加到画布中
app.stage.addChild(rect)
复制代码

上面的代码有几个关键信息:

  1. 首先需要开启交互模式 rect.interactive = true

  2. 如果你希望鼠标移入元素内指针会发生变化,可以设置 rect.cursor = "pointer"

  3. 使用 xxx.on('事件名', 回调函数) 的方式监听指定事件。

如果是在移动端,你就需要使用 tap 代替 click 事件了。

👉 点击查看 `Pixi.js` 更多事件[7]

动画

动画是一种通过在一段时间内连续播放一系列图像来创造运动效果的艺术形式。在计算机图形学中,动画通常是通过在相邻的帧之间进行微小的变化来实现的。Pixi.js是一个强大的2D渲染引擎,可以用于创建各种类型的动画。

Pixi.js 提供了一个处理循环的对象 ticker,它是 Pixi.js 的核心组件之一。这个对象可以帮助我们创建各种类型的动画效果,例如移动、旋转、缩放等。ticker 可以自动更新场景,并在每个帧之间执行我们指定的代码。

比如,我想让矩形旋转起来。

// 创建画布
let app = new PIXI.Application({
  width: 300,
  height: 300
  // resizeTo: window
})

// 将画布添加到页面
document.body.appendChild(app.view)

// 创建矩形
const rectangle = new PIXI.Graphics()
rectangle.beginFill(0xff6600)
rectangle.drawRect(0, 0, 64, 64)
rectangle.endFill()

// 将精灵添加到画布中
app.stage.addChild(rectangle)


app.ticker.add((delta) => {
 // 让矩形旋转起来
  rectangle.rotation += 0.1 * delta
})
复制代码

ticker 是一个用来处理循环的对象,它负责在每一帧更新和重新渲染画布。

delta 是一个与时间相关的因子,通常用于处理动画循环。 delta 是上一帧和当前帧之间经过的时间的比例值。这个值可以用于确保动画在不同性能和速度的设备上尽可能保持一致的表现。

细心的工友可能发现了,矩形是围绕这它的左上角进行旋转的。

如果想让矩形进行中心旋转,可以设置它的 pivot 的值为自身宽高的一半。


// 省略部分代码

// 创建矩形
const rectangle = new PIXI.Graphics()
rectangle.beginFill(0xff6600)
rectangle.drawRect(0, 0, 64, 64)
rectangle.endFill()

// 修改矩形的轴心点
rectangle.pivot.set(32, 32)

// 将矩形移动到画布中间
rectangle.x = app.screen.width / 2
rectangle.y = app.screen.height / 2

app.ticker.add((delta) => {
 // 让矩形旋转起来
  rectangle.rotation += 0.1 * delta
})
复制代码

其他

Pixi.js 的功能远不止这些,由于篇幅有限,无法一一列举所有的功能。

之后有时间我还会继续创作 Pixi.js 相关的文章。之后 ,有时间,下次吧~

推荐阅读

👍《p5.js 光速入门》[8]

👍《Canvas 从入门到劝朋友放弃(图解版)》[9]

👍《SVG 从入门到后悔,怎么不早点学起来(图解版)》[10]

👍《Fabric.js 从入门到\_\_\_\_\_\_\_\_》[11]

点赞 + 关注 + 收藏 = 学会了

关于本文

作者:德育处主任

https://juejin.cn/post/7215100383599870010

最后

欢迎关注【前端瓶子君】✿✿ヽ(°▽°)ノ✿

回复「算法」,加入前端编程源码算法群,每日一道面试题(工作日),第二天瓶子君都会很认真的解答哟!

回复「交流」,吹吹水、聊聊技术、吐吐槽!

回复「阅读」,每日刷刷高质量好文!

如果这篇文章对你有帮助,「在看」是最大的支持

 》》面试官也在看的算法资料《《

“在看和转发”就是最大的支持

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值