What happened?
When a parent DOM element wrapping the CesiumJS canvas has a CSS transform: scale(n) applied (where n != 1), all mouse interaction events (clicks, hover, camera controls) are offset. The registered click position does not match the visual position on the globe.
The root cause is in ScreenSpaceEventHandler.getPosition(). It uses getBoundingClientRect() to get the element's position, but doesn't account for the scale ratio between the bounding rect dimensions and element.clientWidth/Height. When CSS transforms scale the container, getBoundingClientRect() returns the scaled dimensions while clientWidth/Height returns the unscaled dimensions, creating a mismatch.
Expected behavior: Mouse events should register at the correct visual position regardless of CSS transforms applied to ancestor elements.
This issue was surfaced on the forum here: https://community.cesium.com/t/is-there-a-standard-solution-for-interaction-issues-caused-by-transform-or-is-it-an-unexpected-bug/46065. The forum user also proposes a fix they found on the forum. I will repeat here as well:
Approach: Directly modify the source code in ScreenSpaceEventHandler.js, adding scale calculation to the getPosition method:
const rect = element.getBoundingClientRect();
const scaleX = rect.width / element.clientWidth;
const scaleY = rect.height / element.clientHeight;
result.x = (event.clientX - rect.left) / scaleX;
result.y = (event.clientY - rect.top) / scaleY;
Result: Camera controls and interaction events both produce the correct results.
Reproduction steps
- Wrap the Cesium container
div in a parent element with transform: scale(0.5) (or any value != 1)
- Add a billboard or entity to the scene
- Click on the billboard. The click registers at an offset position, not where the billboard visually appears
Sandcastle example
https://sandcastle.cesium.com/#c=ZZLdauMwEIVfZfCy4CxZ2SUb0jpuWMheFvaisL0RlLE1cURlyUhyQlry7iv/1S29sTVnznyckS3rxlgPPwAd7MnJtoaDNTXwqOwrHm25loPpEbUo0XlFk2dWeh/XpdHOw0nSmSzcg6bzSGX/ei2euHujPUpNlkeLfnKYYaS99JIcQyHiN64BGuOCYnQ2kfZofTihXrEuxh+qLJGLf27WbH232WyW8Ctl6er2drVYdoBCKlUYtCKDHggga6woC/kZS/qzSwb284OpzLM5kVV4YY2ueNQjruF5XWyjZZQ7f1G068Tf47W0VsUB5KluFIZkSdGWL+RZ6dywGsA3b1G7g7H1k8VmiiGkCxOXDAplypftIM7rYuGMaj2NDW+aDNKxUHTwc3WWwh8zuEnT76NyJFkd/SfpPUIGrkRFccrWi7535TpPpr1yIU8gxT2PPmXmUb/z3P3yGaFU6FzoHFqlHuVr+CV2eRL8HXR8f8Qrg0Lq6u9w2Z35eLN7GETGWJ6E8n1+DmWMKtB+YP8H
Environment
Browser: Chrome (148.0.7778.97 (Official Build) (64-bit))
CesiumJS Version: 1.141.0
Operating System: Windows 11
AI acknowledgment
What happened?
When a parent DOM element wrapping the CesiumJS canvas has a CSS
transform: scale(n)applied (where n != 1), all mouse interaction events (clicks, hover, camera controls) are offset. The registered click position does not match the visual position on the globe.The root cause is in
ScreenSpaceEventHandler.getPosition(). It usesgetBoundingClientRect()to get the element's position, but doesn't account for the scale ratio between the bounding rect dimensions andelement.clientWidth/Height. When CSS transforms scale the container,getBoundingClientRect()returns the scaled dimensions whileclientWidth/Heightreturns the unscaled dimensions, creating a mismatch.Expected behavior: Mouse events should register at the correct visual position regardless of CSS transforms applied to ancestor elements.
This issue was surfaced on the forum here: https://community.cesium.com/t/is-there-a-standard-solution-for-interaction-issues-caused-by-transform-or-is-it-an-unexpected-bug/46065. The forum user also proposes a fix they found on the forum. I will repeat here as well:
Reproduction steps
divin a parent element withtransform: scale(0.5)(or any value != 1)Sandcastle example
https://sandcastle.cesium.com/#c=ZZLdauMwEIVfZfCy4CxZ2SUb0jpuWMheFvaisL0RlLE1cURlyUhyQlry7iv/1S29sTVnznyckS3rxlgPPwAd7MnJtoaDNTXwqOwrHm25loPpEbUo0XlFk2dWeh/XpdHOw0nSmSzcg6bzSGX/ei2euHujPUpNlkeLfnKYYaS99JIcQyHiN64BGuOCYnQ2kfZofTihXrEuxh+qLJGLf27WbH232WyW8Ctl6er2drVYdoBCKlUYtCKDHggga6woC/kZS/qzSwb284OpzLM5kVV4YY2ueNQjruF5XWyjZZQ7f1G068Tf47W0VsUB5KluFIZkSdGWL+RZ6dywGsA3b1G7g7H1k8VmiiGkCxOXDAplypftIM7rYuGMaj2NDW+aDNKxUHTwc3WWwh8zuEnT76NyJFkd/SfpPUIGrkRFccrWi7535TpPpr1yIU8gxT2PPmXmUb/z3P3yGaFU6FzoHFqlHuVr+CV2eRL8HXR8f8Qrg0Lq6u9w2Z35eLN7GETGWJ6E8n1+DmWMKtB+YP8H
Environment
Browser: Chrome (148.0.7778.97 (Official Build) (64-bit))
CesiumJS Version: 1.141.0
Operating System: Windows 11
AI acknowledgment