跳至内容

useScenePick ​

响应式封装 Cesium.Scene.pick:根据屏幕坐标拾取场景中的第一个对象,结果放入响应式引用。传入坐标(ref/getter)后自动节流执行拾取,相同条件下结果复用缓存;适合鼠标悬停高亮或把结果接入悬浮面板等响应式状态。

Usage ​

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

const cursorPosition = shallowRef<Cesium.Cartesian2>();

// track mouse move to get screen position
useScreenSpaceEventHandler(Cesium.ScreenSpaceEventType.MOUSE_MOVE, (movement: { endPosition: Cesium.Cartesian2 }) => {
  cursorPosition.value = movement.endPosition.clone();
});

// use scene pick to pick entity at cursor
const pick = useScenePick(cursorPosition, {
  width: 3,
  height: 3,
});

// show pick result
const pickInfo = computed(() => {
  if (!pick.value)
    return 'No object picked';
  if (pick.value.id instanceof Cesium.Entity) {
    return `Picked Entity: ${pick.value.id.name || 'unnamed'}`;
  }
  if (pick.value.primitive) {
    return `Picked Primitive: ${(pick.value.primitive as any).id?.name || 'unnamed'}`;
  }
  return `Picked: ${JSON.stringify(pick.value)}`;
});

const entities = useEntity([
  new Cesium.Entity({
    name: 'Red Box',
    position: Cesium.Cartesian3.fromDegrees(120, 30, 500),
    box: {
      dimensions: new Cesium.Cartesian3(2000, 2000, 800),
      material: Cesium.Color.RED,
    },
  }),
  new Cesium.Entity({
    name: 'Blue Box',
    position: Cesium.Cartesian3.fromDegrees(120.02, 30, 500),
    box: {
      dimensions: new Cesium.Cartesian3(2000, 2000, 800),
      material: Cesium.Color.BLUE,
    },
  }),
]);

const viewer = useViewer();
watchEffect(() => {
  if (viewer.value && entities.value) {
    viewer.value.flyTo(entities.value, { duration: 1 });
  }
});
</script>

<template>
  <div class="p-10px">
    {{ pickInfo }}
  </div>
</template>
ts
import * as Cesium from 'cesium';
import { useScenePick, useScreenSpaceEventHandler } from 'vesium';
import { shallowRef } from 'vue';

const cursorPosition = shallowRef<Cesium.Cartesian2>();
useScreenSpaceEventHandler(Cesium.ScreenSpaceEventType.MOUSE_MOVE, (m) => {
  cursorPosition.value = m.endPosition.clone();
});
const pick = useScenePick(cursorPosition);
if (pick.value?.id instanceof Cesium.Entity) {
  console.log(pick.value.id.name);
}

配置项 ​

  • isActive - 是否激活拾取,默认 true;为 false 时结果重置为 undefined,支持 ref/getter 动态控制。
  • throttled - 坐标变化的节流采样间隔(毫秒),默认 8。
  • width / height - 拾取矩形宽高,默认 3,透传给 scene.pick 并参与结果缓存判断。

返回值 ​

  • 返回 Readonly<ShallowRef<ScenePickResult | undefined>>:拾取结果(id、primitive 等字段对应 scene.pick,完整字段见类型定义),未拾取到任何对象时为 undefined。

注意事项 ​

  • 坐标变化先节流(默认 8ms),高频鼠标移动不会每次都触发 scene.pick。
  • viewer 不存在、位置为空或 isActive 为 false 时,结果重置为 undefined。
  • scene.pick 抛错时打印错误日志并将结果置为 undefined。

Type Definitions ​

typescript
import type { ScenePickResult } from '@vesium/shared';
import type { Cartesian2 } from 'cesium';
import type { MaybeRefOrGetter, ShallowRef } from 'vue';
export interface UseScenePickOptions {
    /**
     * Whether to active the event listener.
     * @default true
     */
    isActive?: MaybeRefOrGetter<boolean>;
    /**
     * Throttled sampling (ms)
     * @default 8
     */
    throttled?: number;
    /**
     * The width of the pick rectangle.
     * @default 3
     */
    width?: MaybeRefOrGetter<number | undefined>;
    /**
     * The height of the pick rectangle.
     * @default 3
     */
    height?: MaybeRefOrGetter<number | undefined>;
}
/**
 * Uses the `scene.pick` function in Cesium's Scene object to perform screen point picking,
 * return a computed property containing the pick result, or undefined if no object is picked.
 *
 * @param windowPosition The screen coordinates of the pick point.
 */
export declare function useScenePick(windowPosition: MaybeRefOrGetter<Cartesian2 | undefined>, options?: UseScenePickOptions): Readonly<ShallowRef<ScenePickResult | undefined>>;