外观
3D · 相机与屏幕交互
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 视角参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
duration | number | Cesium 自动计算 | 飞行动画时长,单位为秒;仅 flyTo 支持 |
heading | number | 0 | 水平方向,0 表示朝北,单位为度 |
pitch | number | -90 | 俯视角度,-90 为垂直向下,-45 为倾斜观察 |
roll | number | 0 | 相机翻滚角度,普通地图业务通常不用修改 |
自动查看一组坐标或实体
查看园区边界、地块列表时,不需要自己计算中心点和相机高度,直接传入全部坐标:
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);