卷帘对比,是在同一个三维场景里通过拖拽分割线查看左右/上下两边图层的效果。使用Cesium实现卷帘对比,最关键是设置图层的splitDirection属性。
官网中的【卷帘对比】例子:
1. 创建场景
const viewer = new Cesium.Viewer("cesiumContainer");
2. 自定义分割线样式,监听鼠标/控制器的动作
(1)根据UI设计稿完成分割线的渲染,利用Vue3的Teleport将分割线穿插到body页面中。
<Teleport to="body">
<div id="slider" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave">
<div id="optionOne" class="option">方案一</div>
<div id="optionTwo" class="option">方案二</div>
<div id="sliderButton"></div>
</div>
</Teleport>
(2)由于设计中分割线的不同状态是不同的样式,因此仅利用原生鼠标监听事件不足以完成需求,还需要使用Cesium的事件监听。其中:鼠标左键动作:LEFT_UP、LEFT_DOWN;鼠标移动动作:MOUSE_MOVE;触摸板两指动作:PINCH_START、PINCH_END。
const slider = document.getElementById('slider')
const sliderButton = document.getElementById('sliderButton')
viewer.scene.splitPosition = slider.offsetLeft / slider.parentElement.offsetWidth
const handler = new Cesium.ScreenSpaceEventHandler(slider)
let moveActive = false
let left = '0' // 分割线 left 位置
function move(movement) {
if (!moveActive) {
return
}
const relativeOffset = movement.endPosition.x
const splitPosition = (slider.offsetLeft + relativeOffset) / slider.parentElement.offsetWidth
left = `${100.0 * splitPosition}%`
slider.style.left = left
sliderButton.style.top = movement.endPosition.y - 30 + 'px'
viewer.scene.splitPosition = splitPosition
}
handler.setInputAction(function () {
moveActive = true
slider.style.backgroundColor = '#fff'
}, Cesium.ScreenSpaceEventType.LEFT_DOWN)
handler.setInputAction(function () {
moveActive = true
slider.style.backgroundColor = '#fff'
}, Cesium.ScreenSpaceEventType.PINCH_START)
handler.setInputAction(move, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
handler.setInputAction(move, Cesium.ScreenSpaceEventType.PINCH_MOVE)
handler.setInputAction(function () {
moveActive = false
slider.style.backgroundColor = '#3953ff'
sliderButton.style.display = 'none'
}, Cesium.ScreenSpaceEventType.LEFT_UP)
handler.setInputAction(function () {
moveActive = false
slider.style.backgroundColor = '#3953ff'
sliderButton.style.display = 'none'
}, Cesium.ScreenSpaceEventType.PINCH_END)
3. 加载不同类型图层资源,设置卷帘分屏
由于本次需求是在目录树中勾选方案一/方案二图层资源,因此需判断是将图层加载到分割线的左侧还是右侧。本次动图例子中,是左右两边加载相同图层,左侧透明度设置为0.7。
const splitDirection =
state.currentRollerType === 'left' ? Cesium.SplitDirection.LEFT : Cesium.SplitDirection.RIGHT
三维图层:
tileset.splitDirection = splitDirection
影像图层:
imageryLayer.splitDirection = splitDirection
4. 总结
以上就是基于Cesium卷帘对比的实现, ^-^ 在进行卷帘对比功能的开发时,还需注意一些细节部分,如分割线拖拽到视图边缘时的处理。