为什么在缩放容器后 pointerdown 事件传递到错误的 PIXI.Container?附上测试用例

Why is pointerdown event delivered to a wrong PIXI.Container after scaling containers up and down? Test case attached

我有一个名为 Tile 的自定义 class 扩展 PIXI.Container

它被实例化了3次并存储在变量中:rgb

首先我水平拖动 3 个方块(即将方块保持在第 4 行):

一段时间后,当我单击 中间 磁贴时, 磁贴的 onDragStart 方法错误被调用(在下面的屏幕截图中你可以看到我点击了蓝色的瓷砖,但是绿色已经升起):

所以 pointerdown 事件在错误的对象上调用!

我觉得根本原因是 Tile 对象在单击时会放大,因此 Pixi.js 认为它应该将事件传递给仍然很大的对象。

但我还没有想出解决方法或解决方法。

下面是针对我的问题的完整而简单的测试用例。

这个错误对我来说总是可以重现的,只需将图块移动 5-10 次,您就能看到它。

function Tile(color, onDragStart, onDragMove, onDragEnd, x, y) {
    PIXI.Container.call(this);

    this.x = x;
    this.y = y;

    this.interactive = true;
    this.buttonMode = true;
    this.on('pointerdown', onDragStart)
        .on('pointermove', onDragMove)
        .on('pointerup', onDragEnd)
        .on('pointerupoutside', onDragEnd);

    this.graph = new PIXI.Graphics();
    this.graph.beginFill(color);
    this.graph.drawRect(0, 0, Tile.W, Tile.W);
    this.graph.endFill();
    this.addChild(this.graph);
    this.cacheAsBitmap = true;
}

Tile.W = 100;
Tile.prototype = Object.create(PIXI.Container.prototype);
Tile.prototype.constructor = Tile;

Tile.prototype.startDragging = function() {
    this.scale.x = 1.6;
    this.scale.y = 1.6;
    this.alpha = 0.8;
};

Tile.prototype.stopDragging = function() {
    this.scale.x = 1;
    this.scale.y = 1;
    this.alpha = 1;
    // align x, y to the checker board grid
    this.x = Tile.W * Math.floor((this.x + Tile.W / 2) / Tile.W);
    this.y = Tile.W * Math.floor((this.y + Tile.W / 2) / Tile.W);
};

var app = new PIXI.Application({
    width: Tile.W * 8,
    height: Tile.W * 8,
    view: document.getElementById('pixiCanvas'),
    backgroundColor: 0xFFFFFF
});

var background = new PIXI.Graphics();
for (var i = 0; i < 8; i++) {
    for (var j = 0; j < 8; j++) {
        if ((i + j) % 2 == 0) {
            background.beginFill(0xCCCCFF);
            background.drawRect(i * Tile.W, j * Tile.W, Tile.W, Tile.W);
            background.endFill();
        }
    }
}
app.stage.addChild(background);

var r = new Tile(0xFF0000, onDragStart, onDragMove, onDragEnd, 3 * Tile.W, 3 * Tile.W);
var g = new Tile(0x00FF00, onDragStart, onDragMove, onDragEnd, 4 * Tile.W, 3 * Tile.W);
var b = new Tile(0x0000FF, onDragStart, onDragMove, onDragEnd, 5 * Tile.W, 3 * Tile.W);

app.stage.addChild(r);
app.stage.addChild(g);
app.stage.addChild(b);

function onDragStart(ev) {
    this.data = ev.data;
    var pos = this.data.getLocalPosition(this.parent);
    this.x = pos.x - this.width / 2;
    this.y = pos.y - this.height / 2;
    // put the tile on top
    app.stage.removeChild(this);
    app.stage.addChild(this);
    this.startDragging();
}

function onDragMove() {
    if (this.data) {
        var pos = this.data.getLocalPosition(this.parent);
        this.x = pos.x - this.width / 2;
        this.y = pos.y - this.height / 2;
    }
}

function onDragEnd() {
    if (this.data) {
        var pos = this.data.getLocalPosition(this.parent);
        this.data = null;
        // the next 2 lines are not needed here, but 
        // in my real game I put the tile beneath the HUD
        app.stage.removeChild(this);
        app.stage.addChildAt(this, app.stage.children.length);
        this.stopDragging();
    }
}
#pixiCanvas {
      width: 100%;
      height: 100%;
      background: #CCF;
      box-sizing: border-box;
      border: 4px red dotted;
}
<canvas id="pixiCanvas"></canvas>
<script src="https://cdn.jsdelivr.net/npm/pixi.js@5.3.7/dist/pixi.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/pixi.js-legacy@5.3.7/dist/pixi-legacy.min.js"></script>

另外我创建了 issue 7233 at Github and you can also see the bug in my real app:

到目前为止我已经尝试过但没有帮助的事情:

用-

修复了它
this.hitArea = new PIXI.Rectangle(0, 0, Tile.W, Tile.W);