Cesium实现拖拽放大缩小实体圆功能

Cesium实现拖拽放大缩小实体圆功能

  1. 场景说明: 使用cesium绘制一个实体圆,需要在实体圆上标注一点,通过拖拽这个点实现对实体圆的放大缩小功能:
  2. 实现原理: 绘制一个实体圆,并绘制一个锚点,锚点的位置是通过圆形与半径计算出来的。
    3: 关键代码:
    第一步: 绘制实体圆:

假设圆心为center = {
longitude: 121,
latitude: 30
}
radius: 300 // 半径为300米
viewer.entities.add({
            position: Cesium.Cartesian3.fromDegrees(
             center.longitude,
              center.latitude
            ),
            name: 'rangeCircle',
            id: 'rang001', // 实体圆的Id
            ellipse: {
              semiMinorAxis: radius,
              semiMajorAxis: radius,
              height: 400,
              material: Cesium.Color.fromCssColorString('rgba(0, 0, 0, 0.3)'),
              outline: true,
              outlineColor: Cesium.Color.fromCssColorString('rgba(255, 255, 255, 0.5)'),
              outlineWidth: 3.0
            }
          })

第二歩: 绘制实体圆上的锚点:

// 判断锚点是否存在
const hasDrag = viewer.entities.getById('drag001')
// 根据圆心和半径计算锚点的经纬度
getDragPosition (center, radius) {
    let dragPosition = null
    const ellRadius = 6371 // 地球半径,单位千米
    const distance = radius / 1000 // 将周边范围单位转化为千米
    const dlng = 2 * Math.asin(Math.sin(distance / (2 * ellRadius)) / Math.cos(center.latitude * Math.PI / 180))
    const dlat = distance / ellRadius
    const parseLng = dlng * 180 / Math.PI
    const parseLat = dlat * 180 / Math.PI
    dragPosition = {
      parseLng: parseLng,
      parseLat: parseLat
    }
    return dragPosition
  }
      const dragPosition = getDragPosition(center, radius)
        // 判断是否存在拖拽锚点
        if (hasDrag) {
          hasDrag.position = Cesium.Cartesian3.fromDegrees(
            center.longitude + dragPosition.parseLng,
            center.latitude,
            400 // 高度
          )
          hasDrag.label.text = radius + '米'
        } else {
          viewer.entities.add({
            id: 'drag001',
            position: Cesium.Cartesian3.fromDegrees(
              center.longitude + dragPosition.parseLng,
              center.latitude,
              400
            ),
            billboard: {
              image: require('@/images/ResponseModule/drag.svg'), // 锚点图片自己找就可以
              show: true,
              horizontalOrigin: Cesium.HorizontalOrigin.RIGHT,
              verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
              pixelOffset: new Cesium.Cartesian2(8, 0)
            },
            label: {
              text: `${radius}`,
              font: '16px',
              fillColor: Cesium.Color.fromCssColorString('rgba(255, 255, 255, 1)'),
              outlineColor: Cesium.Color.fromCssColorString('rgba(255, 255, 255, 1)'),
              style: Cesium.LabelStyle.FILL_AND_OUTLINE,
              showBackground: true,
              horizontalOrigin: Cesium.HorizontalOrigin.RIGHT,
              verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
              pixelOffset: new Cesium.Cartesian2(50, 10)
            }
          })
        }

第三步: 拖拽放大缩小实现

// 鼠标左键事件
leftDown () { this.downHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas)
    this.downHandler.setInputAction((movement) => {
     const picked = this.viewer.scene.pick(movement.position)
        // 当鼠标左键点击拖拽点的时候
        if (Cesium.defined(picked) && picked.id._id === 'drag001') {
          this.viewer.scene.screenSpaceCameraController.enableRotate = false
          this.zoom()
        }
    }, Cesium.ScreenSpaceEventType.LEFT_DOWN)
  },
  // 
  zoom () {
    this.zoomHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas)
    this.zoomHandler.setInputAction((movement) => {
      // const ray = this.viewer.camera.getPickRay(movement.endPosition)
      // const cartesian = this.viewer.scene.pickPosition(movement.endPosition)
      const ray = this.viewer.camera.getPickRay(movement.endPosition)
      const cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene)
      // const parseCartesian = MapConverData.cartesianToLng(cartesian)
      this.positions.push(cartesian)
      // 获取到拖动点的位置距离圆心的距离作为半径
      this.radius = parseFloat(this.getSpaceDistance(this.positions))
      const hasRange = this.viewer.entities.getById('rang001')
      // 在鼠标移动的过程中不断更新拖拽点的位置
      const dragPosition = getDragPosition(center, this.radius)
      const hasDrag = this.viewer.entities.getById('drag001')
      if (hasDrag) {
        hasDrag.position = Cesium.Cartesian3.fromDegrees(
          center.longitude + dragPosition.parseLng,
          center.latitude,
          400
        )
        hasDrag.label.text = this.radius + '米'
      }
      // 设置实体圆的半径
      if (hasRange) {
        hasRange.ellipse.semiMinorAxis = new Cesium.CallbackProperty(() => {
          return this.radius
        }, false)
        hasRange.ellipse.semiMajorAxis = new Cesium.CallbackProperty(() => {
          return this.radius
        }, false)
      }
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
  },
  // 右键点击完成标点
 rightClick () {
    const rightHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas)
    rightHandler.setInputAction((movement) => {
    // 设置鼠标默认样式
      this.viewer._container.style.cursor = 'default'
      this.viewer.scene.screenSpaceCameraController.enableRotate = true
      // 销毁鼠标左键和鼠标move事件
      this.zoomHandler = this.zoomHandler && this.zoomHandler.destroy(Cesium.ScreenSpaceEventType.MOUSE_MOVE)
      this.downHandler = this.downHandler && this.downHandler.destroy(Cesium.ScreenSpaceEventType.LEFT_DOWN)
    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
  },
  // 只计算起点和终点的距离
  getSpaceDistance (positions) {
    var distance = 0
    const start = _head(positions)
    const end = _last(positions)
    // for (var i = 0; i < positions.length - 1; i++) {
    var point1cartographic = Cesium.Cartographic.fromCartesian(start)
    var point2cartographic = Cesium.Cartographic.fromCartesian(end)
    /** 根据经纬度计算出距离**/
    var geodesic = new Cesium.EllipsoidGeodesic()
    geodesic.setEndPoints(point1cartographic, point2cartographic)
    var s = geodesic.surfaceDistance
    // 返回两点之间的距离
    s = Math.sqrt(Math.pow(s, 2) + Math.pow(point2cartographic.height - point1cartographic.height, 2))
    distance = distance + s
    // }
    return Math.round(distance)
  }
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值