眨个眼就学会了PixiJS

本文简介

带尬猴,我是德育处主任


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


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



环境搭建

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

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

创建好项目后就需要安装 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 历史版本下载地址


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地址:https://www.npmjs.com/package/@pixi/graphics-extras



起步

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


创建画布

分2步走:

  1. 使用 Pixi.js 创建画布
  2. 将画布添加到页面中

file

<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 创建出来的画布背景默认是黑色的。你可以在创建画布时手动设置背景色。

file

// 省略部分代码...

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() 方法可以销毁画布。

file

<button onclick="">删除画布</button>

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

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

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

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

file

// 省略部分代码

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 是矩形的宽高。

看个例子:

file

// 创建画布
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 参数可以控制四个角的圆角半径。

file

// 创建画布
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 它也不会怪你的,因为它本身有默认值嘛。

file

// 省略部分代码...

graphics.drawRoundedRect(50, 50, 200, 100)

倒角矩形 (drawChamferRect)

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

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


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 为负数时,圆角就会向内凹进去。

file

<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 是定义矩形左上角的位置。

file

// 创建画布
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 的椭圆 ,这点大家需要注意一下。

file

// 创建画布
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,
	......
])

file

// 创建画布
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

举个例子

file

<!-- 引入 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 是旋转弧度。

举个例子

file

<!-- 引入 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 ,画出来的是一个没缺口的环形。

file

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

// 创建画布
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)

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

file

// 创建环形
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.

file

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

// 创建图形类
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() 里都可以传入一个坐标点,表示折线的顶点。

file

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

// 创建图形类
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() 方法会将折线的起点和终点连接起来。

file

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

// 创建图形类
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

file

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

// 创建图形类
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 从入门到劝朋友放弃(图解版)》 有讲到,有兴趣的工友可以去看看。


Pixi.jsarcTo() 语法

arcTo(x1, y1, x2, y2, radius)
  • x1y1 是弧线的起始点坐标。
  • x2y2 是弧线的终点坐标。
  • radius 是弧线的半径。

file

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

// 创建图形类
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个控制点,理解了二次贝塞尔曲线就能理解三次贝塞尔曲线。

file

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

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

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

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

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

file

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


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

二次贝塞尔曲线

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

语法

quadraticCurveTo(cpX, cpY, toX, toY)
  • 在使用 quadraticCurveTo() 前,需要使用 moveTo() 定义曲线的起点。
  • quadraticCurveTo()cpXcpY 是第一个控制点。
  • toXtoY 是第二个控制点。

file

// 创建图形类
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() 配合。

file

// 创建图形类
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('文本内容') 这样用即可,样式部分我放在后面讲解。

file

// 创建画布
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. 将“精灵”添加到画布中

file

// 创建画布
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之间的值表示不同程度的半透明。

颜色关键字

举个例子(颜色关键字)

file

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

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

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

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

// 绘制操作
graphics.endFill()

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

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


十六进制

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

file

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

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

// 或者
graphics.beginFill(0x0fff00)

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

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

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


数值

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

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

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

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

file

我用手算法计算了一下,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个参数。

file

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() 方法,第一个参数是文本内容,第二个参数是样式对象。

常用配置

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

file

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

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

app.stage.addChild(text)

字距

letterSpacing 属性可以设置字距。

file

const text = new PIXI.Text(
  "雷猴",
  {
    fill: 'yellow', // 填充色
    letterSpacing: 20
  }
)

文本投影

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

具体用法请看代码注释。

file

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

文本渐变填充

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

file

const text = new PIXI.Text(
  "雷猴",
  {
    fontSize: 60,
    fill: ['yellow', 'red', 'purple', 'blue'], // 填充色
  }
)

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

file

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. 将图片设置为文本的遮罩层

file

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 属性,让文本变得更粗。

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

file


图片样式

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


宽高

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

file

// 省略部分代码

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

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

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

位置

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

file

// 省略部分代码

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

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

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

旋转

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

file

// 省略部分代码

// 加载图片
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

file

// 省略部分代码

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

// 设置不透明度
sprite.alpha = 0.6


滤镜

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

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


模糊滤镜

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

file

// 创建画布
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

file

// 省略部分代码

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

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

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

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

file

const alphaFilter = new PIXI.AlphaFilter(2)

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



事件

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

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


鼠标点击事件

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

完整用法如下所示

file

// 创建画布
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 更多事件



动画

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

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

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

file

// 创建画布
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 的值为自身宽高的一半。

file

// 省略部分代码

// 创建矩形
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 光速入门》

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

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

👍《Fabric.js 从入门到________》


点赞 + 关注 + 收藏 = 学会了
代码仓库

posted @ 2023-10-27 16:58  德育处主任  阅读(99)  评论(0编辑  收藏  举报