useElementOverlay
把 HTML 元素锚定到 Cesium 场景中的某个地理坐标,并随相机变化实时更新位置。基于 scene.postUpdate 每帧自动同步,内置对齐(horizontal/vertical)、像素偏移(offset)、贴地(clampToGround)与坐标系选择,返回 x/y/style 并默认自动应用到目标元素。
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>配置项
horizontal/vertical- 水平/垂直对齐原点,默认'center'/'bottom';可选'center' | 'left' | 'right'/'center' | 'bottom' | 'top'。offset- 锚点基础上的像素偏移,默认{ x: 0, y: 0 }。referenceWindow-true时相对浏览器视口定位(加上 canvas 在页面中的位置),缺省相对 Cesium 画布。applyStyle- 是否自动把left/top应用到目标元素,默认true;设为false时自行绑定返回的x/y/style。clampToGround- 是否把坐标贴到地表(通过scene.clampToHeight),需要地形或 3D Tiles 等高度数据。
返回值
x/y- 像素坐标(ComputedRef<number>,保留 1 位小数,已按对齐原点扣除元素自身尺寸);style- 可直接绑定到元素的 CSS 字符串(如left:100px;top:200px;)。
注意事项
clampToGround依赖scene.clampToHeight,地形未加载或无法贴地时回退为原始坐标;demo 使用世界地形展示该效果,需要网络连接与 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;