【Cesium】卷帘对比

259 阅读2分钟

卷帘对比,是在同一个三维场景里通过拖拽分割线查看左右/上下两边图层的效果。使用Cesium实现卷帘对比,最关键是设置图层的splitDirection属性。

官网中的【卷帘对比】例子:

​编辑

  1. 创建场景
const viewer = new Cesium.Viewer("cesiumContainer");

  1. 自定义分割线样式,监听鼠标/控制器的动作

(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)

  1. 加载不同类型图层资源,设置卷帘分屏

由于本次需求是在目录树中勾选方案一/方案二图层资源,因此需判断是将图层加载到分割线的左侧还是右侧。本次动图例子中,是左右两边加载相同图层,左侧透明度设置为0.7。

const splitDirection =
        state.currentRollerType === 'left' ? Cesium.SplitDirection.LEFT : Cesium.SplitDirection.RIGHT

三维图层:

tileset.splitDirection = splitDirection

影像图层: 

imageryLayer.splitDirection = splitDirection

​编辑

  1. 总结

以上就是基于Cesium卷帘对比的实现, ^-^  在进行卷帘对比功能的开发时,还需注意一些细节部分,如分割线拖拽到视图边缘时的处理。