Skip to content

3D · 相机与屏幕交互 ​

相机控制和屏幕拾取都依赖原生 Viewer。必须等 CesiumMap 的 load 事件返回 Viewer 后再调用。

相机飞入 ​

相机操作统一通过 useCamera 使用。将 CesiumMap 的 load 事件返回值保存到 viewerRef,之后可以在按钮、接口回调或其他业务方法中随时控制视角。

下面是一个可以直接使用的完整示例:

vue
<template>
  <div class="map-page">
    <div class="map-actions">
      <button @click="flyToOrchard">飞入园区</button>
    </div>

    <CesiumMap @load="onMapLoad" />
  </div>
</template>

<script setup lang="ts">
import { shallowRef } from "vue";
import {
  CesiumMap,
  useCamera,
  type Viewer,
} from "scene-mapping-gis/3d";

const viewerRef = shallowRef<Viewer | null>(null);
const { flyTo } = useCamera({ viewer: viewerRef });

function onMapLoad(viewer: Viewer) {
  viewerRef.value = viewer;
}

/** 平滑飞到一个园区中心点;height 越大,看到的地图范围越大。 */
function flyToOrchard() {
  flyTo([117.203, 39.123, 3000], {
    duration: 2,
    heading: 0,
    pitch: -55,
  });
}
</script>

<style scoped>
.map-page { position: relative; height: 600px; }
.map-actions { position: absolute; z-index: 1; top: 12px; left: 12px; }
</style>

单个位置的坐标格式 ​

flyTo 和 setView 都支持下面两种写法,经度、纬度使用度,高度使用米:

ts
flyTo([117.203, 39.123, 3000]);

flyTo({
  longitude: 117.203,
  latitude: 39.123,
  height: 3000,
});

height 表示相机高度,不是园区或地块高度。定位后看到的范围太小,就增大 height;相机距离地面太远,就减小 height。

相机方法 ​

方法适用场景返回值
flyTo(position, options?)带动画飞到一个经纬度位置void
setView(position, options?)初始化或立即切换视角,不播放动画void
getPosition()读取当前相机位置和朝向,用于保存、恢复视角CameraPositionResult | undefined
flyToBoundingSphere(positions, options?)根据一组经纬度自动调整视野,适合查看园区或多个地块void
flyToEntities(entities, options?)根据一组已有 Entity 自动调整视野void

flyTo / setView 视角参数 ​

参数类型默认值说明
durationnumberCesium 自动计算飞行动画时长,单位为秒;仅 flyTo 支持
headingnumber0水平方向,0 表示朝北,单位为度
pitchnumber-90俯视角度,-90 为垂直向下,-45 为倾斜观察
rollnumber0相机翻滚角度,普通地图业务通常不用修改

自动查看一组坐标或实体 ​

查看园区边界、地块列表时,不需要自己计算中心点和相机高度,直接传入全部坐标:

ts
flyToBoundingSphere(boundaryPositions, {
  duration: 2,
  offset: {
    heading: 0,
    pitch: -60,
    range: 3000,
  },
});

如果已经通过 CesiumEntity 或 useEntityManager 创建了实体,也可以直接传入实体数组:

ts
flyToEntities(entityManager.getAllEntities(), {
  duration: 2,
  offset: { pitch: -60, range: 3000 },
});

offset.range 是相机与目标范围的距离,单位为米;不传或设置为 0 时由 Cesium 根据范围自动计算。

调用后相机没有移动

确认 CesiumMap 已触发 load,并且已经执行 viewerRef.value = viewer。Viewer 还未创建完成时调用相机方法不会生效。

鼠标默认交互:左键拖动旋转,滚轮缩放,按住鼠标中键拖动调整俯仰视角。

屏幕事件与拾取 ​

CesiumMap 直接提供左键单击、右键单击、左键双击和鼠标移动事件,并同时返回鼠标位置、地图经纬度以及命中的 Entity。不需要额外引入鼠标事件 Hook。

vue
<template>
  <CesiumMap
    @left-click="onLeftClick"
    @right-click="onRightClick"
    @double-click="onDoubleClick"
    @mouse-move="onMouseMove"
  />
</template>

<script setup lang="ts">
import { CesiumMap, type PickResult } from "scene-mapping-gis/3d";

function onLeftClick(result: PickResult) {
  console.log("地图坐标", result.position);
  console.log("点中的实体", result.pickedEntity);
}

function onRightClick(result: PickResult) {
  console.log("右键单击", result);
}

function onDoubleClick(result: PickResult) {
  console.log("左键双击", result);
}

function onMouseMove(result: PickResult) {
  console.log("鼠标当前位置", result.position);
}
</script>

可用的鼠标事件 ​

组件事件触发时机常见用途
left-click鼠标左键单击地图选择地块、Marker 或获取点击经纬度
right-click鼠标右键单击地图打开右键菜单、结束业务操作
double-click鼠标左键双击地图打开详情、快速定位
mouse-move鼠标在地图上移动悬停提示、实时显示经纬度

回调统一返回 PickResult:

字段说明
windowPosition鼠标在地图 Canvas 内的像素坐标,包含 x、y
position地图经纬度和高度,格式为 { longitude, latitude, height };点击天空时为 undefined
pickedEntity鼠标命中的 Cesium Entity;没有点中实体时为 undefined

pickedEntity 只表示 Cesium Entity,例如 CesiumEntity 创建的点、线、面。Primitive 或 3D Tiles 的原始图元不会作为 pickedEntity 返回。

只有传入对应的组件事件时,CesiumMap 才会注册该鼠标操作。没有使用 mouse-move 时不会持续执行高频坐标拾取;使用后如果业务处理较复杂,建议在业务回调中自行节流。组件卸载时会自动清理全部事件。

直接使用工具函数 ​

一般业务推荐使用 useCamera 和 CesiumMap 的鼠标事件。需要在普通 TypeScript 文件中操作原生 Viewer 时,也可以直接使用下面这些公开工具:

工具作用
flyTo(viewer, position, options?)传入原生 Viewer,飞到一个位置
setView(viewer, position, options?)传入原生 Viewer,立即切换视角
getCameraPosition(viewer)获取当前相机位置和朝向
flyToBoundingSphere(viewer, positions, options?)让一组坐标完整进入视野
pickPosition(viewer, windowPosition)根据屏幕像素位置获取经纬度
pickEntity(viewer, windowPosition)根据屏幕像素位置获取命中的 Entity
toCartesian3(position)将业务经纬度转换成 Cesium 世界坐标
toCartographic(cartesian)转成 Cesium 弧度制经纬度和高度
toDegrees(cartesian)将 Cesium 世界坐标转换成经纬度
defaultViewerOptions()获取 CesiumMap 使用的默认 Viewer 配置

类型声明 ​

ts
import { flyTo, pickPosition } from "scene-mapping-gis/3d";

flyTo(viewer, [117.203, 39.123, 3000], { duration: 2 });
const position = pickPosition(viewer, windowPosition);