跳至内容

useGraphicEvent

为 Cesium 图形(Entity、Primitive、DataSource 等)统一处理点击、悬停、拖拽事件与鼠标指针样式:内部自动 scene.pick,只在命中目标图形时触发回调。监听器存于 WeakMap,图形被回收或组件卸载时自动释放,无需担心内存泄漏。

Usage

vue
<script setup lang="ts">
import { canvasCoordToCartesian, toProperty } from '@vesium/shared';
import * as Cesium from 'cesium';
import { useEntity, useGraphicEvent, useViewer } from 'vesium';
import { watchEffect } from 'vue';

const viewer = useViewer();

watchEffect(() => {
  viewer.value?.camera.flyTo({
    destination: Cesium.Cartesian3.fromDegrees(150, 12.5, 9000000),
  });
});

const graphicEvent = useGraphicEvent();

// =========[CLICK]============
useEntity(() => {
  const entity = new Cesium.Entity({
    position: Cesium.Cartesian3.fromDegrees(140, 10),
    point: { pixelSize: 15 },
    label: {
      font: '14px sans-serif',
      pixelOffset: new Cesium.Cartesian2(0, 20),
      text: 'CLICK ME',
    },
  });
  graphicEvent.add(
    entity,
    'LEFT_CLICK',
    (_params) => {
      const color = new Cesium.ConstantProperty(Cesium.Color.RED);
      entity!.point!.color = color;
      entity!.label!.fillColor = color;
      entity!.label!.text = new Cesium.ConstantProperty('CLICKED');
    },
  );
  return entity;
});

// =========[HOVER]============
useEntity(() => {
  const entity = new Cesium.Entity({
    position: Cesium.Cartesian3.fromDegrees(150, 10),
    point: { pixelSize: 15 },
    label: {
      font: '14px sans-serif',
      pixelOffset: new Cesium.Cartesian2(0, 20),
      text: 'HOVER ME',
    },
  });
  graphicEvent.add(
    entity,
    'HOVER',
    (params) => {
      const color = params.hovering ? Cesium.Color.RED : undefined;
      entity!.point!.color = toProperty(color);
      entity!.label!.fillColor = toProperty(color);
      entity!.label!.text = toProperty(params.hovering ? 'HOVERING' : 'HOVER ME');
    },
  );
  return entity;
});

// =========[DRAG]============
useEntity(() => {
  const entity = new Cesium.Entity({
    position: Cesium.Cartesian3.fromDegrees(160, 10),
    point: { pixelSize: 15 },
    label: {
      font: '14px sans-serif',
      pixelOffset: new Cesium.Cartesian2(0, 20),
      text: 'DRAG ME',
    },
  });

  graphicEvent.add(
    entity,
    'DRAG',
    (params) => {
      const color = params.dragging ? Cesium.Color.RED : undefined;
      entity!.point!.color = toProperty(color);
      entity!.label!.fillColor = toProperty(color);
      entity!.label!.text = toProperty(params.dragging ? 'DRAGGING' : 'DRAG ME');
      // lock camera
      params.dragging && params.lockCamera();

      // update position
      const position = canvasCoordToCartesian(params.event.endPosition, viewer.value!.scene);
      if (position) {
        entity!.position = new Cesium.CallbackPositionProperty(() => position, false);
      }
    },
  );
  return entity;
});
</script>

<template>
  <div />
</template>
ts
import * as Cesium from 'cesium';
import { useEntity, useGraphicEvent } from 'vesium';

const graphicEvent = useGraphicEvent();
useEntity(() => {
  const entity = new Cesium.Entity({
    position: Cesium.Cartesian3.fromDegrees(140, 10),
    point: { pixelSize: 15 }, // 有图形的实体才能被 scene.pick 命中
  });
  graphicEvent.add(entity, 'LEFT_CLICK', ({ pick }) => {
    console.log('clicked', pick.id);
  });
  graphicEvent.add(entity, 'HOVER', ({ hovering }) => {
    entity.point!.color = new Cesium.ConstantProperty(hovering ? Cesium.Color.RED : Cesium.Color.WHITE);
  });
  return entity;
});

配置项(add 的 options)

  • cursor - 悬停时的指针样式,默认 'pointer';可为字符串或 (event: GraphicHoverEvent) => string | null | undefined 函数。
  • dragCursor - 拖拽中的指针样式,默认 'crosshair'(仅 DRAG 事件生效,且只在拖拽中显示)。

返回值

  • add(graphic, type, listener, options?) - 注册监听并返回移除函数;graphic'global' 表示任意图形命中都触发,type'HOVER''DRAG' 或位置事件(如 'LEFT_CLICK',完整列表见类型定义)。
  • remove / clear - 移除 / 清空指定图形的监听;cleartype'all' 清空该图形全部监听。
  • 事件载荷:位置事件为 { event, pick }HOVER 增加 hovering: booleanDRAG 增加 dragging: booleanlockCamera()

注意事项

  • graphic 可为任意能被 scene.pick 命中的对象(EntityPrimitiveDataSource 等);'global' 使用内部符号存储,需通过 remove/clearadd 返回的移除函数显式清理。无需担心内存泄漏:图形被回收后 WeakMap 中对应监听自动释放,内部屏幕事件随组件卸载自动停止。

Type Definitions

typescript
import type { Nullable } from '@vesium/shared';
import type { Entity } from 'cesium';
import type { GraphicDragEvent } from './useDrag';
import type { GraphicHoverEvent } from './useHover';
import type { GraphicPositionedEvent, PositionedEventType } from './usePositioned';
export type CesiumGraphic = Entity | any;
export type GraphicEventType = PositionedEventType | 'HOVER' | 'DRAG';
export type GraphicEventListener<T extends GraphicEventType> = T extends 'DRAG' ? (event: GraphicDragEvent) => void : T extends 'HOVER' ? (event: GraphicHoverEvent) => void : (event: GraphicPositionedEvent) => void;
export type removeFn = () => void;
export interface AddGraphicEventOptions {
    /**
     * The cursor style to use when the mouse is over the graphic.
     * @default 'pointer'
     */
    cursor?: Nullable<string> | ((event: GraphicHoverEvent) => Nullable<string>);
    /**
     * The cursor style to use when the mouse is over the graphic during a drag operation.
     * @default 'crosshair'
     */
    dragCursor?: Nullable<string> | ((event: GraphicHoverEvent) => Nullable<string>);
}
export interface UseGraphicEventReturn {
    /**
     * Add a graphic event listener and return a function to remove it.
     * @param graphic - The graphic object, 'global' indicates the global graphic object.
     * @param type - The event type, 'all' indicates clearing all events.
     * @param listener - The event listener function.
     */
    add: <T extends GraphicEventType>(graphic: CesiumGraphic | 'global', type: T, listener: GraphicEventListener<T>, options?: AddGraphicEventOptions) => removeFn;
    /**
     * Remove a graphic event listener.
     * @param graphic - The graphic object, 'global' indicates the global graphic object.
     * @param type - The event type, 'all' indicates clearing all events.
     * @param listener - The event listener function.
     */
    remove: <T extends GraphicEventType>(graphic: CesiumGraphic | 'global', type: T, listener: GraphicEventListener<T>) => void;
    /**
     * Clear graphic event listeners.
     * @param graphic - The graphic object.
     * @param type - The event type, 'all' indicates clearing all events.
     */
    clear: (graphic: CesiumGraphic | 'global', type: GraphicEventType | 'all') => void;
}
/**
 * Handle graphic event listeners and cursor styles for Cesium graphics.
 * You don't need to overly worry about memory leaks from the function, as it automatically cleans up internally.
 */
export declare function useGraphicEvent(): UseGraphicEventReturn;