前言
笔者在之前使用PIXI.js的时候,经常出现忽略层级而导致画板上的内容不能正常交互的问题。于是便有了写下这篇博客的想法。
zIndex & sortableChildren
要想正确的处理层级问题,离不开zIndex和sortableChildren这两个属性。在介绍之前,我们先来看一个基础的例子。在不设置zIndex的时候,重叠在一起的图形会有怎样的表现。
下面的代码将3个不同颜色矩形添加到stage当中。
const pixiApp = new PIXI.Application({
width: 800,
height: 600,
backgroundColor: 0xffffff
}) // 实例化应用
const {view, stage} = pixiApp
container.append(view) //将生成的canvas添加到页面容器
const offset_x = 50
const offset_y = 50
const width = 100
const height = 100
const rectList = [
{
text: 'box1',
color: 0xdddddd
},
{
text: 'box2',
color: 0x0000ff
},
{
text: 'box3',
color: 0x00ff00
}
]
rectList.forEach(({text, color}, index) => {
const rect = new PIXI.Graphics()
rect.beginFill(color)
rect.drawRect(0, 0, width, height)
rect.endFill()
rect.x = offset_x * index
rect.y = offset_y * index
const rectText = new PIXI.Text(text, new PIXI.TextStyle({
fontSize: 12
}))
rect.addChild(rectText)
stage.addChild(rect)
})
可以发现在后面绘制的图形默认层级会更高,如果我们想修改默认的层级就需要使用上面提到的两个属性。我们对上面的代码做一些修改,实现box2在最上方得效果。
stage.sortableChildren = true //对容器设置该属性后 zIndex才生效
rect.zIndex = 10 //将box2的zIndex属性设置为10
源码实现
PIXI.JS是怎样处理这个层级效果的,我们可以简单看一下相关部分的实现,关键就在Container.ts这个文件中。它在渲染的时候是通过遍历容器中的children,并调用该child的render方法实现的。因此后面添加进入容器中的元素有更高的一个层级。
render(renderer: Renderer): void{
...
//渲染的核心逻辑
for (let i = 0, j = this.children.length; i < j; ++i){
this.children[i].render(renderer);
}
...
}
或许你已经猜到PIXI.JS是怎样实现层级的修改的,没错,就是通过修改children数组的排序。我们来看一下下面这个方法。
updateTransform(): void{
if (this.sortableChildren && this.sortDirty){
this.sortChildren();
}
...//省略部分代码
for (let i = 0, j = this.children.length; i < j; ++i){
const child = this.children[i];
if (child.visible)
{
child.updateTransform();
}
}
}
上面这个方法在每次render的时候就会调用,而sortChildren就是根据child的zIndex进行排序(其中还涉及到相同层级时候的处理)。这就是为啥我们要先设置sortableChildren。上面这个方法不仅仅做层级的变化还涉及了其它一些更新时的变化,这里就不深入讨论。
写在最后
本文简单介绍了一下PIXI.JS是如何处理元素层级,如果有写的不对的地方还望大家多指正。PIXI.JS在渲染性能方面是相当不错的,功能也很强大,而且生态也比较完善,不过就是学习的成本比较高,很多问题都要通过查阅英文博客或者看源码解决。而后面也会在整理一下使用过程中遇到的问题,供大家参考。