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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions