前言:实现了对矩形的自由编辑,但是编辑过程中依旧保持矩形状态
矩形变化
以下是核心代码:
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
},
思路:
- 监听modify编辑方法,结合map的pointermove方法监听点的移动距离
- 监听点的移动距离前,判断拖拽点是左上右下哪一个,根据对应的点计算拖拽过程,计算是否横纵拖拽
根本找不到我这个需求的案例,找到的类似的还要收费,我还是主打共享