Openlayers拖拽修改矩形大小并保持矩形

发布于:2024-07-05 ⋅ 阅读:(14) ⋅ 点赞:(0)

前言:实现了对矩形的自由编辑,但是编辑过程中依旧保持矩形状态

矩形变化

以下是核心代码:

1.引入modify

import { Modify} from 'ol/interaction.js'

2.拖拽开始

初次编辑
tools.mapModify.on('modifystart', (e) => {
      let startFeature = e.features.item(0)
      if (startFeature.get('shape_type') === 'rectangle') {
        isDraggingRectangle = true
        modifyingFeature = startFeature // 设置正在修改的特性
        const coords = modifyingFeature.getGeometry().getCoordinates()[0]
        const draggingCoord = e.mapBrowserEvent.coordinate

        // 找到拖拽的点索引
        draggingPointIndex = coords.findIndex((coord) => coord[0] === draggingCoord[0] && coord[1] === draggingCoord[1])
        oppositeCoordinate = methodEvents.getOppositeCoordinate(draggingPointIndex, coords)

        if (draggingPointIndex === -1) {
          // 查找最近的点,处理在高分辨率下可能存在的浮点数误差
          let minDistance = Infinity
          coords.forEach((coord, index) => {
            const distance = Math.hypot(coord[0] - draggingCoord[0], coord[1] - draggingCoord[1])
            if (distance < minDistance) {
              minDistance = distance
              draggingPointIndex = index
            }
          })
          oppositeCoordinate = methodEvents.getOppositeCoordinate(draggingPointIndex, coords)
        }
        // 保存原始坐标
        originalCoordinates = coords.map((coord) => [...coord])
      } else {
        isDraggingRectangle = false
        draggingPointIndex = -1
        oppositeCoordinate = null
        originalCoordinates = null
      }
    })
   
   编辑结束
   tools.mapModify.on('modifyend', (e) => {
      let editLabelList = e.features.getArray()
      //  handleMoreListToSingleArr是我处理多层级数据方法,可无视
      let newList = methodEvents.handleMoreListToSingleArr(devObj.leftObjMarkList)
      editLabelList.forEach((feature) => {
        const { geometry, svgID } = feature.values_
        if (!svgID) return
        let { flatCoordinates } = geometry
        const coordinates = geometry.getCoordinates()
        const pixelCoordinates = coordinates[0].map((item) => middleMethods.setCoordinatePixel(item).pixelArr[0])

        for (let i = 0; i < newList.length; i++) {
          let label = newList[i]
          if (label.svgID === svgID) {
            label.flatCoordinates = flatCoordinates
            label.points = pixelCoordinates
            break
          }
        }
      })
      //  stringifyDeepData 是序列化方法,克隆用
      const copyListData = methodEvents.stringifyDeepData(devObj.leftObjMarkList)
      mitt.emit('leftBottomAddMarkList', copyListData)
      const dom = document.getElementById('svg')
      dom.style.cursor = 'auto'
      isDraggingRectangle = false
      draggingPointIndex = -1
      oppositeCoordinate = null
      originalCoordinates = null
    })
    
   监听矩形编辑过程
  mousemoveRectangle() {
    tools.mousemoveRectangle = tools.map.on('pointermove', (e) => {
      if (isDraggingRectangle && modifyingFeature && draggingPointIndex !== -1) {
        const geometry = modifyingFeature.getGeometry()
        const currentCoord = e.coordinate
        const newCoordinates = methodEvents.calculateNewCoordinates(draggingPointIndex, currentCoord, originalCoordinates, oppositeCoordinate)
        geometry.setCoordinates([newCoordinates])
        modifyingFeature.changed()
      }
    })
  },

核心方法:

// 获取对角点
  getOppositeCoordinate(index, coordinates) {
    switch (index) {
      case 0:
        return coordinates[2] // 左上对应右下
      case 1:
        return coordinates[3] // 右上对应左下
      case 2:
        return coordinates[0] // 右下对应左上
      case 3:
        return coordinates[1] // 左下对应右上
      default:
        return null
    }
  },
 /**
   * @description 多层级平铺
   * @param {*} list 数组
   */
  handleMoreListToSingleArr(list, key = 'children') {
    let newList = []
    if (!list.length) return newList
    list.forEach((data) => {
      data[key].forEach((child) => {
        newList.push(child)
      })
    })
    return newList
  },
/**
   *
   * @param {*} draggingIndex 对应点位
   * @param {*} currentCoord 拖拽点坐标
   * @param {*} originalCoords 原始坐标
   * @param {*} oppositeCoord 对角点坐标
   * @description
   */
  calculateNewCoordinates(draggingIndex, currentCoord, originalCoords, oppositeCoord) {
    const newCoordinates = originalCoords.map((coord, index) => {
      if (index === draggingIndex) {
        return currentCoord
      } else if (index === (draggingIndex + 2) % 4) {
        return oppositeCoord
      } else if (index === (draggingIndex + 1) % 4) {
        return [currentCoord[0], originalCoords[(draggingIndex + 2) % 4][1]]
      } else {
        return [originalCoords[(draggingIndex + 2) % 4][0], currentCoord[1]]
      }
    })
    if (newCoordinates[0].toString() !== newCoordinates.at(-1).toString()) {
      newCoordinates[newCoordinates.length - 1] = newCoordinates[0]
    }
    return newCoordinates
  },

思路:

  1. 监听modify编辑方法,结合map的pointermove方法监听点的移动距离
  2. 监听点的移动距离前,判断拖拽点是左上右下哪一个,根据对应的点计算拖拽过程,计算是否横纵拖拽

根本找不到我这个需求的案例,找到的类似的还要收费,我还是主打共享


网站公告

今日签到

点亮在社区的每一天
去签到