将 child 添加到 pixi.js 精灵会扭曲 child 的尺寸和位置

Adding child to pixi.js sprite distorts childs dimensions & location

我使用 typescript & pixi.js v4.8.2。这是帮助我创建所有容器的代码。

    let appWidth = app.renderer.view.width
    let appHeight = app.renderer.view.height
    mapContainer = new PIXI.Sprite(PIXI.loader.resources.water_pattern.texture);
    mapContainer.height = app.renderer.view.height
    mapContainer.width = appWidth - appWidth / 5 - appWidth / 14
    mapContainer.x = app.renderer.view.width / 14

    cardContainer = new PIXI.Sprite(PIXI.Texture.WHITE);
    cardContainer.tint = 0x3C2415;
    cardContainer.height = app.renderer.view.height / 2
    cardContainer.width = app.renderer.view.width / 14

    actionContainer = new PIXI.Sprite(PIXI.Texture.WHITE);
    actionContainer.tint = 0x00FF00;
    actionContainer.height = app.renderer.view.height / 2
    actionContainer.width = app.renderer.view.width / 14
    actionContainer.y = app.renderer.view.height / 2

    chatContainer = new PIXI.Sprite(PIXI.Texture.WHITE);
    chatContainer.tint = 0x008080;
    chatContainer.height = app.renderer.view.height / 2
    chatContainer.width = app.renderer.view.width / 5
    chatContainer.x = app.renderer.view.width * 4 / 5

    playerContainer = new PIXI.Sprite(PIXI.Texture.WHITE);
    playerContainer.tint = 0xCCCCCC;
    playerContainer.height = app.renderer.view.height / 2
    playerContainer.width = app.renderer.view.width / 5
    playerContainer.y = app.renderer.view.height / 2
    playerContainer.x = app.renderer.view.width * 4 / 5

    app.stage.addChild(mapContainer, cardContainer, actionContainer, chatContainer, playerContainer)

然后我尝试在容器中创建精灵:

    let settlement = new PIXI.Sprite(PIXI.loader.resources.settlement_red.texture)
    settlement.height = 10
    settlement.width = 10
    settlement.x = 0
    settlement.y = 0
    chatContainer.addChild(settlement)

我的代码的结果是这样的:

房子显然不在 x & y。而且显然不是10到10个像素。为什么会这样?我该如何解决?

请注意,我知道我可以使用 PIXI.Container,但我会添加背景图片。我发现当背景图像是容器的一部分而不是容器内的单独 object 时效果更好,因此我使用了精灵。

最后是我的应用代码:

    app = new PIXI.Application({ // http://pixijs.download/release/docs/PIXI.Application.html
            antialias: true,    // default: false
            forceCanvas: true, // default: false (forces canvas rendering instead of webgl rendering)
        }
    );
    app.renderer.autoResize = true;
    app.renderer.view.style.position = "absolute";
    app.renderer.view.style.display = "block";
    app.renderer.autoResize = true;
    app.renderer.resize(window.innerWidth, window.innerHeight);
    document.body.appendChild(app.view);

Ivon 在 this forum 上发布了答案。

Its a serious issue that exists for all the time of PixiJS, it even predates pixi , it exists in Flash!

The issue follows:

  1. width and height props are evil. They are not first-class citizens. https://github.com/pixijs/pixi.js/wiki/v4-Gotchas#width-and-height-are-evil

  2. the behaviour cant be changed because of compatibility with flash. https://github.com/pixijs/pixi.js/blob/dev/src/core/display/Container.js#L570

Look here: https://github.com/pixijs/pixi.js/blob/dev/src/core/sprites/Sprite.js#L373 . Extend Sprite class, override getLocalBounds method that way it ignores children, leave only the code inside that "if".

我这样解决了我的问题;我没有使用 PIXI.Sprite,而是使用了 PIXI.Container

export class ViewContainer extends PIXI.Container {
    bg: PIXI.Sprite

    constructor(x: number, y: number, w: number, h: number, color: number, container: Container) {
        // as we're extending a class, we need to call the inherited classes constructor first
        super()
        this.x = x
        this.y = y
        this.bg = new PIXI.Sprite(PIXI.Texture.WHITE)
        this.bg.tint = color
        this.bg.width = w
        this.bg.height = h
        this.addChild(this.bg)
        container.addChild(this)
    }

    addBorder() {
        let border = new PIXI.Graphics();
        border.lineStyle(.1,0xFFFFFF,1);
        border.drawRect(0,0,10,10);
        border.endFill();
        this.bg.addChild(border)
    }
}

然后我用这段代码创建了容器

function createContainers() {
    let appW = app.renderer.view.width
    let appH = app.renderer.view.height

    cardContainer = new ViewContainer(0, appH*10/11, appW*2/5, appH/11, 0x3C2415, app.stage)
    actionContainer = new ViewContainer(appW*2/5, appH*10/11, appW*2/5, appH/11, 0x00FF00, app.stage)
    chatContainer = new ViewContainer(appW*4/5, 0, appW/5, appH/2, 0x008080, app.stage)
    playerContainer = new ViewContainer(appW*4/5, appH/2, appW/5, appH/2, 0xCCCCCC, app.stage)
    mapContainer = new ViewContainer(0, 0, appW - appW/5, appH*10/11, 0x0000FF, app.stage)
}

现在我可以使用这样的代码来定位所有对象:

let settlement = new PIXI.Sprite(PIXI.loader.resources.settlement_red.texture)
settlement.height = 10
settlement.width = 10
settlement.x = 0
settlement.y = 0
chatContainer.addChild(settlement)