编辑节点拉伸旋转复制粘贴删除
import RightMenu from '@/components/RightMenu/index';components: {RightMenu
},
rightMenuType: '', //可操作图形状态
isRightMenu: false, //是否可以操作图形
//鼠标右击
rightMenu(e) {if (this.type === 'move' && this.activeData.length > 0 && this.rightMenuType === '') {this.$refs.RightMenu.showModal(e.offsetX, e.offsetY);} else {return;}
},
//右键菜单返回
backRightMenu(e) {this.rightMenuType = e;this.isRightMenu = true;//编辑图形switch (e) {case 'editPoint':this.redrawMap();break;}
}
if(this.activeData.length > 0 && this.isRightMenu) {//编辑图形switch (this.rightMenuType) {case 'editPoint':drawMap.drawRectangle(this.activeData, 'editPoint');break;}
}
// 开启吸附功能 记录是否处于吸附状态
if (this.activeData.length > 0 && ['editPoint'].includes(this.rightMenuType)) {this.activeData.map((item, idx) => {let result = mathUtils.attractPixel([x, y], item)if(result.isAttract && this.isMouseClick) {if(idx === 0 || idx === this.activeData.length - 1) {this.$set(this.activeData,this.activeData.length - 1,[x,y]);}this.$set(this.activeData,idx,[x,y]);}})
}
// 计算两点距离
dealLength(start, end) {var a = end.x - start.x;var b = end.y - start.y;return Math.sqrt(a * a + b * b);
},
// 鼠标点击位置和目标点相距<=吸附半径则吸附到目标点
attractPixel(point1, pointTarget, pixelArea = adsorptionDistance) {const len = this.dealLength({x: point1[0],y: point1[1]}, {x: pointTarget[0],y: pointTarget[1]})const finalPoint = len <= pixelArea ? pointTarget : point1const isAttract = len <= pixelAreareturn {finalPoint,isAttract}
},
//鼠标按下判断选中边线按下插入节点
if (this.activeData.length > 0 && ['editPoint'].includes(this.rightMenuType)) {const pointData = mathUtils.attractOnCheckLine({x,y}, this.activeData);if(pointData && pointData.overIdx >= 0) {this.activeData.splice(pointData.overIdx + 1, 0, [x, y])}
}
// 计算当前点到所有线段的垂点,小于5px,则吸附
attractOnCheckLine(point, coordinates) {for (var i = 0; i < coordinates.length; i++) {if (this.checkPoint(coordinates[i], point)) {return {x: coordinates[i][0],y: coordinates[i][1],idx: i};}}for (var i = 0; i < coordinates.length - 1; i++) {var pt = this.pointToSegDist(point.x, point.y, coordinates[i][0], coordinates[i][1],coordinates[i + 1][0], coordinates[i + 1][1], Math.pow(adsorptionDistance, 2));if (pt) {pt.overIdx = ireturn pt;}}return null;
},
checkPoint(target, point) {if (point.x >= target[0] - adsorptionDistance &&point.x <= target[0] + adsorptionDistance &&point.y >= target[1] - adsorptionDistance &&point.y <= target[1] + adsorptionDistance) {return true;} else {return false;}
},
pointToSegDist(x, y, x1, y1, x2, y2, dist) {var cross = (x2 - x1) * (x - x1) + (y2 - y1) * (y - y1);if (cross <= 0) return null;var d2 = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);if (cross >= d2) return null;var r = cross / d2;var px = x1 + (x2 - x1) * r;var py = y1 + (y2 - y1) * r;var dis = (x - px) * (x - px) + (py - y) * (py - y);if (dis <= dist) { // adsorptionDistance * adsorptionDistancereturn {x: px,y: py};}
},
选择矩形圆形
import * as turf from "@/utils/turf.es";let adsorptionDistance = 6
const mathUtils = {// 计算两点距离dealLength(start, end) {var a = end.x - start.x;var b = end.y - start.y;return Math.sqrt(a * a + b * b);},// 计算点到线垂点的方法calculateVerticalPoint(arr) {const point = arr[2]var x1 = arr[0][0];var y1 = arr[0][1];var x2 = arr[1][0];var y2 = arr[1][1]if (x1 == x2 && y1 == y2) {return [point[0], point[1]];}var m = point[0];var n = point[1];var a = y2 - y1;var b = x1 - x2;var c = x2 * y1 - x1 * y2;var x3 = (b * b * m - a * b * n - a * c) / (a * a + b * b);var y3 = (a * a * n - a * b * m - b * c) / (a * a + b * b);return [Math.round(x3 * 100) / 100, Math.round(y3 * 100) / 100];},// 根据垂点计算平行点calculatePoint(vPoint, point, point2) {const x = point[0] - vPoint[0] + point2[0]const y = point[1] - vPoint[1] + point2[1]return [x, y]},// 判断点是否在多边形内部或者线上pointInPolygonORLine(point, polygon) {var pt = turf.point(point);var poly = turf.polygon([polygon]);return turf.booleanPointInPolygon(pt, poly)},// 获取多边形的中心点getPolygonCenter(arr) {var polygon = turf.polygon([arr]);var center = turf.centerOfMass(polygon);return center.geometry.coordinates},// 获取缩放后的坐标scalePoint(oGeo, scale, oCenter) {const newGeo = []const moveX = oCenter[0] * scale - oCenter[0]const moveY = oCenter[1] * scale - oCenter[1]for (var item of oGeo) {const x = item[0] * scale - moveXconst y = item[1] * scale - moveYnewGeo.push([x, y])}return newGeo},// 鼠标点击位置和目标点相距<=吸附半径则吸附到目标点attractPixel(point1, pointTarget, pixelArea = adsorptionDistance) {const len = this.dealLength({x: point1[0],y: point1[1]}, {x: pointTarget[0],y: pointTarget[1]})const finalPoint = len <= pixelArea ? pointTarget : point1const isAttract = len <= pixelAreareturn {finalPoint,isAttract}},// 计算当前点到所有线段的垂点,小于5px,则吸附attractOnCheckLine(point, coordinates) {for (var i = 0; i < coordinates.length; i++) {if (this.checkPoint(coordinates[i], point)) {return {x: coordinates[i][0],y: coordinates[i][1],idx: i};}}for (var i = 0; i < coordinates.length - 1; i++) {var pt = this.pointToSegDist(point.x, point.y, coordinates[i][0], coordinates[i][1],coordinates[i + 1][0], coordinates[i + 1][1], Math.pow(adsorptionDistance, 2));if (pt) {pt.overIdx = ireturn pt;}}return null;},checkPoint(target, point) {if (point.x >= target[0] - adsorptionDistance &&point.x <= target[0] + adsorptionDistance &&point.y >= target[1] - adsorptionDistance &&point.y <= target[1] + adsorptionDistance) {return true;} else {return false;}},pointToSegDist(x, y, x1, y1, x2, y2, dist) {var cross = (x2 - x1) * (x - x1) + (y2 - y1) * (y - y1);if (cross <= 0) return null;var d2 = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);if (cross >= d2) return null;var r = cross / d2;var px = x1 + (x2 - x1) * r;var py = y1 + (y2 - y1) * r;var dis = (x - px) * (x - px) + (py - y) * (py - y);if (dis <= dist) { // adsorptionDistance * adsorptionDistancereturn {x: px,y: py};}},
}export default mathUtils;
let ctxDom, mapCtx; //初始化必要参数const drawMap = {//初始化地图initMap({id,w,h} = obj) {ctxDom = idid.width = wid.height = hmapCtx = id.getContext("2d");},//地图重绘redrawMap() {mapCtx.clearRect(0, 0, ctxDom.width, ctxDom.height);},//画圆drawCircle({x,y,r,strokeStyle = '#1289ff80', //边框色fillStyle = '#fff0', //填充色} = obj) {mapCtx.beginPath();mapCtx.fillStyle = fillStyle;mapCtx.setLineDash([]);mapCtx.strokeStyle = strokeStylemapCtx.arc(x, y, r, 0, 2 * Math.PI);mapCtx.closePath();mapCtx.stroke();mapCtx.fill();},drawRectangle(arr, isCheck) {mapCtx.strokeStyle = isCheck ? '#1289ff' : '#1289ff80';mapCtx.fillStyle = isCheck ? '#ffffff80' : '#fff0';mapCtx.lineWidth = 2;mapCtx.setLineDash([]);mapCtx.lineJoin = 'bevel';mapCtx.beginPath();mapCtx.moveTo(arr[0][0], arr[0][1]);for (let i = 1; i < arr.length; i++) {mapCtx.lineTo(arr[i][0], arr[i][1]);}mapCtx.stroke();mapCtx.fill();if (isCheck == 'editPoint') {for (let i = 0; i < arr.length; i++) {this.drawCircle({x: arr[i][0],y: arr[i][1],r: 3,strokeStyle: '#1289ff80',fillStyle: '#fff'})}}},
}export default drawMap
组件页请参考顶部!!!
下一篇:1.Redis【介绍与安装】