Skip to content

DOMElement with a non-zero origin drifts under camera zoom (scene-level only) #7329

Description

@moufmouf

Version: Phaser 4.2.0 / 4.2.1 (logic also present in 3.x); WebGL & Canvas; any browser.

Description

A DOMElement added directly to the Scene with a non-zero origin (default 0.5, 0.5) drifts from its world position when camera.zoom !== 1, by exactly (originX·width, originY·height)·(1 − camera.zoom). It is sliding bottom-right as you zoom out. The same DOMElement nested in a Container does not drift, so the two render paths are inconsistent.

Minimal example

https://phaser.io/sandbox/f0eb3f05

Root cause (found by Claude Code after some digging around)

In DOMElementCSSRenderer.js, camMatrix.translate(-dx, -dy) bakes the origin offset into the CSS matrix in both branches. The parentMatrix branch then keeps transform-origin: 0% 0% (offset applied once → correct). The else branch also sets transform-origin: (100·origin)% (offset applied twice). The two cancel only when the matrix's linear scale (camera zoom) is 1; under zoom the residual is originX·width·(1 − zoom). The transform-origin percentage lines date to 2019 (v3); the March-2025 v4 refactor preserved the behavior: it typically surfaces once an app drives a real camera zoom on scene-level DOM elements. I tested on v3.80 and the bug was already present.

I'll provide a PR to fix the issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions