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-truepositions relative to the browser viewport (adding the canvas's page position); omitted positions relative to the Cesium canvas.applyStyle- Whether to applyleft/topto the target automatically, defaults totrue; set tofalseto bind the returnedx/y/styleyourself.clampToGround- Whether to clamp the coordinate to the ground (viascene.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
clampToGroundrelies onscene.clampToHeightand 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;