Skip to content

useElementOverlay

Anchor an HTML element to a geographic coordinate in the Cesium scene and update its position in real time as the camera moves. Based on scene.postUpdate, the position is synced on every frame with built-in alignment (horizontal/vertical), pixel offset (offset), ground clamping (clampToGround), and coordinate-system selection; it returns x/y/style and applies them to the target element by default.

Usage

vue
<script lang="ts" setup>
import * as Cesium from 'cesium';
import { useElementOverlay, useEntity, useViewer } from 'vesium';
import { shallowRef, watchEffect } from 'vue';

const viewer = useViewer();
const position = shallowRef(Cesium.Cartesian3.fromDegrees(100.04215139520794, 31.320830427363237, 0));

watchEffect(async () => {
  if (viewer.value?.scene) {
    viewer.value.scene.terrainProvider = await Cesium.createWorldTerrainAsync();
  }
});

useEntity(new Cesium.Entity({
  position: position.value,
  point: {
    pixelSize: 10,
    color: Cesium.Color.YELLOW,
    heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
  },
}));

watchEffect(() => {
  viewer.value?.camera.setView({
    destination: Cesium.Cartesian3.fromDegrees(100.04215139520794, 31.320830427363237, 100000),
  });
});

const elRef = shallowRef<HTMLDivElement>();

const { x, y, style } = useElementOverlay(elRef, position, {
  offset: { x: 0, y: -20 },
  clampToGround: true,
});
</script>

<template>
  <teleport v-if="viewer" :to="viewer?.container">
    <div ref="elRef" class="text-white p-20px bg-black/50 absolute">
      <h4>useElementOverlay</h4>
      <pre>{{ JSON.stringify({ x, y, style }, undefined, 2) }}</pre>
    </div>
  </teleport>
</template>
vue
<script setup lang="ts">
import * as Cesium from 'cesium';
import { useElementOverlay } from 'vesium';
import { shallowRef } from 'vue';

const elRef = shallowRef<HTMLDivElement>();
const position = shallowRef(Cesium.Cartesian3.fromDegrees(120, 30, 0));
const { x, y, style } = useElementOverlay(elRef, position, { offset: { x: 0, y: -20 } });
</script>

<template>
  <div ref="elRef" class="absolute" :style="style">
    My Label
  </div>
</template>

Options

  • horizontal / vertical - The horizontal/vertical origin, defaults to 'center' / 'bottom'; one of 'center' | 'left' | 'right' / 'center' | 'bottom' | 'top'.
  • offset - The pixel offset on top of the anchor, defaults to { x: 0, y: 0 }.
  • referenceWindow - true positions relative to the browser viewport (adding the canvas's page position); omitted positions relative to the Cesium canvas.
  • applyStyle - Whether to apply left/top to the target automatically, defaults to true; set to false to bind the returned x/y/style yourself.
  • clampToGround - Whether to clamp the coordinate to the ground (via scene.clampToHeight); requires height data such as terrain or 3D Tiles.

Return Value

  • x / y - Pixel coordinates (ComputedRef<number>, 1 decimal place, already offset by the element's own size per the alignment origin); style - a CSS string ready to bind, e.g. left:100px;top:200px;.

Notes

  • clampToGround relies on scene.clampToHeight and falls back to the original coordinate when terrain is not loaded or clamping fails; the demo uses world terrain, which requires network access and an Ion token.

Type Definitions

typescript
import type { CommonCoord } from '@vesium/shared';
import type { MaybeComputedElementRef } from '@vueuse/core';
import type { ComputedRef, MaybeRefOrGetter } from 'vue';
export interface UseElementOverlayOptions {
    /**
     * Horizontal origin of the target element
     * @default `center`
     */
    horizontal?: MaybeRefOrGetter<'center' | 'left' | 'right' | undefined>;
    /**
     * Vertical origin of the target element
     * @default `bottom`
     */
    vertical?: MaybeRefOrGetter<'center' | 'bottom' | 'top' | undefined>;
    /**
     * Pixel offset presented by the target element
     * @default {x:0,y:0}
     */
    offset?: MaybeRefOrGetter<{
        x?: number;
        y?: number;
    } | undefined>;
    /**
     * The reference element for calculating the position of the target element
     *  - `true` refer to the browser viewport
     *  - `false` refer to the Cesium canvas
     */
    referenceWindow?: MaybeRefOrGetter<boolean>;
    /**
     * Whether to apply style to the target element
     * @default true
     */
    applyStyle?: MaybeRefOrGetter<boolean>;
    /**
     * The position will be clamped to the ground
     *
     */
    clampToGround?: MaybeRefOrGetter<boolean>;
}
export interface UseElementOverlayReturn {
    /**
     * Calculation result of the target element's horizontal direction
     */
    x: ComputedRef<number>;
    /**
     * Calculation result of the target element's vertical direction
     */
    y: ComputedRef<number>;
    /**
     * Calculation `css` of the target element
     */
    style: ComputedRef<string | undefined>;
}
/**
 * Cesium HTMLElement Overlay
 */
export declare function useElementOverlay(target?: MaybeComputedElementRef, position?: MaybeRefOrGetter<CommonCoord | undefined>, options?: UseElementOverlayOptions): UseElementOverlayReturn;