Skip to content

fix(html-layer): keep HTML overlays aligned when the viewer container has an offset - #223

Open
FenjuFu wants to merge 1 commit into
dvt3d:masterfrom
FenjuFu:fix/html-layer-container-offset
Open

fix(html-layer): keep HTML overlays aligned when the viewer container has an offset#223
FenjuFu wants to merge 1 commit into
dvt3d:masterfrom
FenjuFu:fix/html-layer-container-offset

Conversation

@FenjuFu

@FenjuFu FenjuFu commented Aug 16, 2026

Copy link
Copy Markdown

What

Fixes #212HtmlLayer overlays drift vertically when the viewer container has an offset in the page (a container with a fixed height, or nested in an iframe). The issue does not occur in v2.x.

Root cause

HtmlLayer positions its DOM overlays from Cesium.SceneTransforms.worldToWindowCoordinates(), which already returns canvas-relative pixels. It then adds viewer.getOffset() — the container's getBoundingClientRect().left/top, i.e. its viewport position:

const offset = this._viewer.getOffset()
// ...
windowCoord.x += offset.x
windowCoord.y += offset.y

The overlays are position: absolute .div-icon elements inside .viewer-layers. When the container fills the screen at viewport (0,0), getOffset() is ~{0,0} and the extra term is invisible. Once the container sits lower in the page (e.g. height: 95px), rect.top grows and every overlay is pushed down by the container offset — the reported symptom. .viewer-layers also has no positioning of its own, so the overlays lacked a canvas-aligned positioned ancestor and the getOffset() term was only compensating by coincidence at the origin.

Change

  • HtmlLayer.js: drop the getOffset() addition; the window coordinates are already canvas-relative.
  • viewer.scss: give .viewer-layers an explicit box that overlaps the canvas so absolutely positioned overlays resolve against a canvas-aligned ancestor regardless of the outer container. pointer-events is disabled on the pane and re-enabled on its children so map interaction is preserved.

Together these make HTML overlays independent of where the viewer container sits in the page (fixed height, nested, iframe), which is the expected behaviour described in the issue.

Verification note

This was derived from source analysis and restores the pre-v5 behaviour. I could not run a full local build to verify in a browser, so please double-check the pointer-events change against the other panes mounted on layerContainer (WindLayer, HeatMapLayer, ChartLayer) to confirm their interaction is unaffected. Happy to adjust.

… has an offset

HtmlLayer positioned DOM overlays by adding viewer.getOffset() (the
container's viewport rect) to the canvas-relative coordinates returned by
Cesium.SceneTransforms.worldToWindowCoordinates(). When the container was
not at the top-left of the page (a container with a fixed height, or nested
in an iframe), this shifted every overlay by the container offset. It only
looked correct for a full-screen container at viewport (0,0).

- Drop the getOffset() addition in HtmlLayer; the window coordinates are
  already canvas-relative.
- Give .viewer-layers an explicit box that overlaps the canvas so absolutely
  positioned overlays resolve against a canvas-aligned ancestor regardless of
  the outer container. pointer-events is disabled on the pane and re-enabled
  on its children so map interaction is preserved.

Fixes dvt3d#212

Signed-off-by: FenjuFu <[email protected]>
@FenjuFu

FenjuFu commented Aug 16, 2026

Copy link
Copy Markdown
Author

Verified locally against a dc-sdk v5.0.0 build.

Repro: the viewer container is placed below a 200px header, so container.getBoundingClientRect().top ≈ 200. Three DivIcons and three Cesium-rendered Points are added at identical coordinates; the in-canvas points are the ground truth.

Before (current dev): .viewer-layers is position: static, and every DivIcon renders +200px below its point — exactly the container's page offset.

point (viewport x,y) div-icon center ΔY
408, 556 408, 756 +200
450, 519 450, 719 +200
492, 581 492, 781 +200

After (this PR): the offset addition is gone and .viewer-layers is the canvas-aligned box, so every DivIcon lands on its point — ΔY = 0 at all three, with the container still 200px down the page.

point (viewport x,y) div-icon center ΔY
213, 707 213, 707 0
247, 673 247, 673 0
281, 732 281, 732 0

pointer-events: the change follows the standard overlay-pane pattern (pane pointer-events: none, children auto) so the pane doesn't intercept map interaction while div-icons stay clickable. I did not specifically exercise the other panes mounted on layerContainer (WindLayer / HeatMapLayer / ChartLayer), so a maintainer check there is still welcome.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

HtmlLayer 在容器高度设定下出现偏移问题,旧版(v2.x)无此问题

1 participant