同上一篇 模型旋转、缩放 一样,模型拖动也是很常见的操作。
我在网上找了几篇关于模型拖放的博客,修改并进行了封装。
使用方式
npm install cesium-entity-drag
import Drag from 'cesium-entity-drag'
const drag = new Drag(window.viewer)
// start drag
drag.enable()
// or disable
drag.disable()
源码
如果你还有其他定制的需求,可以自行修改源码:
import * as Cesium from 'cesium'
export default class Drag {
constructor(viewer) {
this._viewer = viewer
this.entity = null
this.handler = null
this.moving = false
this._leftDown = this._leftDownHandler.bind(this)
this._leftUp = this._leftUpHandler.bind(this)
this._move = this._moveHandler.bind(this)
this.handler = new Cesium.ScreenSpaceEventHandler(this._viewer.canvas)
}
enable() {
this.handler.setInputAction(this._leftDown, Cesium.ScreenSpaceEventType.LEFT_DOWN);
this.handler.setInputAction(this._leftUp, Cesium.ScreenSpaceEventType.LEFT_UP)
this.handler.setInputAction(this._move, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
}
disable() {
this._viewer.scene.screenSpaceCameraController.enableRotate = true
this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOWN)
this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_UP)
this.handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE)
this.moving = false
this.entity = null
}
_leftDownHandler(e) {
this.entity = this._viewer.scene.pick(e.position)
this.moving = true
if (this.entity) {
this._viewer.scene.screenSpaceCameraController.enableRotate = false
}
}
_leftUpHandler() {
this.moving = false
this.entity = null
this._viewer.scene.screenSpaceCameraController.enableRotate = true
}
_moveHandler(e) {
if (this.moving && this.entity) {
const ray = this._viewer.camera.getPickRay(e.endPosition)
const cartesian = this._viewer.scene.globe.pick(ray, this._viewer.scene)
this.entity.id.position = new Cesium.CallbackProperty(function () {
return cartesian
}, false)
}
}
}
因为工作关系,也没有进行仔细测试。如果你遇到什么问题,欢迎在下方留言,或者在github仓库 提交 issue。
更新(2021年6月21日)
拖动模型还遇到了一个问题, 在_moveHandler中,无论我们是拾取地形坐标、还是球体坐标,总是无法给到正确的高度。
我将拖动进行了修改,仅支持水平拖动,高度的修改请自行实现。原理很简单,将空间坐标cartesian转换成经纬度(实际上是弧度),提取原来的高度,覆盖当前高度。
_moveHandler(e) {
if (this.moving && this.entity && this.entity.id) {
const ray = this._viewer.camera.getPickRay(e.endPosition)
const cartesian = this._viewer.scene.globe.pick(ray, this._viewer.scene)
const ellipsoid = viewer.scene.globe.ellipsoid
const c = ellipsoid.cartesianToCartographic(cartesian)
const origin = this.entity.id.position.getValue()
const cc = ellipsoid.cartesianToCartographic(origin)
this.entity.id.position = new Cesium.CallbackProperty(function () {
return new Cesium.Cartesian3.fromRadians(c.longitude, c.latitude, cc.height)
}, false)
}
代码已更新到npm
本想进行额外的拓展,比如增加高度、旋转操作,但这些并不涉及到鼠标事件,也不复杂,放进来未必能减轻开发人员的负担。