mapbox-gl-draw 绘制态势标绘-双箭头

本文介绍了如何使用mapbox-gl-draw库创建并绘制双箭头,包括`CreateDoubleArrow.js`和`DrawDoubleArrow.js`两个关键步骤,详细阐述了在前端项目中结合Vue.js和JavaScript实现态势标绘的详细过程。

CreateDoubleArrow.js

function getMid(t,e){return[(t[0]+e[0])/2,(t[1]+e[1])/2]}function getDistance(t,e){return Math.sqrt(Math.pow(t[0]-e[0],2)+Math.pow(t[1]-e[1],2))}function getAngle(t,e,i){let n=getAzimuth(e,t)-getAzimuth(e,i);return n<0?n+TWO_PI:n}function getAzimuth(t,e){let i,n=Math.asin(Math.abs(e[1]-t[1])/getDistance(t,e));return e[1]>=t[1]&&e[0]>=t[0]?i=n+Math.PI:e[1]>=t[1]&&e[0]<t[0]?i=TWO_PI-n:e[1]<t[1]&&e[0]<t[0]?i=n:e[1]<t[1]&&e[0]>=t[0]&&(i=Math.PI-n),i}function getSymetricPoint(t,e,i,n,r){let o=getAzimuth(t,e),c=r?o+i:o-i,g=n*Math.cos(c),a=n*Math.sin(c);return[e[0]+g,e[1]+a]}function calculateSymmetryPoint(t,e,i){let n,r,o,c,g=getMid(t,e),a=getDistance(g,i),P=getAngle(t,g,i);return P<HALF_PI?(r=a*Math.sin(P),o=a*Math.cos(P),c=getSymetricPoint(t,g,HALF_PI,r,!1),n=getSymetricPoint(g,c,HALF_PI,o,!0)):P>=HALF_PI&&P<Math.PI?(r=a*Math.sin(Math.PI-P),o=a*Math.cos(Math.PI-P),c=getSymetricPoint(t,g,HALF_PI,r,!1),n=getSymetricPoint(g,c,HALF_PI,o,!1)):P>=Math.PI&&P<1.5*Math.PI?(r=a*Math.sin(P-Math.PI),o=a*Math.cos(P-Math.PI),c=getSymetricPoint(t,g,HALF_PI,r,!0),n=getSymetricPoint(g,c,HALF_PI,o,!0)):(r=a*Math.sin(2*Math.PI-P),o=a*Math.cos(2*Math.PI-P),c=getSymetricPoint(t,g,HALF_PI,r,!0),n=getSymetricPoint(g,c,HALF_PI,o,!1)),n}function getBaseLength(t){return Math.pow(wholeDistance(t),.99)}function wholeDistance(t){let e=0;for(let i=0;i<t.length-1;i++)e+=getDistance(t[i],t[i+1]);return e}function getAngleOfThreePoints(t,e,i){let n=getAzimuth(e,t)-getAzimuth(e,i);return n<0?n+TWO_PI:n}function getArrowHeadPoints(t,e,i){let n=getBaseLength(t),r=n*headHeightFactor,o=t[t.length-1],c=(getDistance(e,i),r*headWidthFactor),g=r*neckWidthFactor,a=r*neckHeightFactor,P=getSymetricPoint(t[t.length-2],o,0,r,!0),h=getSymetricPoint(t[t.length-2],o,0,a,!0),s=getSymetricPoint(o,P,HALF_PI,c,!1),l=getSymetricPoint(o,P,HALF_PI,c,!0),u=getSymetricPoint(o,h,HALF_PI,g,!1),A=getSymetricPoint(o,h,HALF_PI,g,!0);return[u,s,o,l,A]}function getArrowBodyPoints(t,e,i,n){let r=wholeDistance(t),o=getBaseLength(t),c=o*n,g=getDistance(e,i),a=(c-g)/2,P=0,h=[],s=[];for(let e=1;e<t.length-1;e++){let i=getAngleOfThreePoints(t[e-1],t[e],t[e+1])/2;P+=getDistance(t[e-1],t[e]);let n=(c/2-P/r*a)/Math.sin(i),o=getSymetricPoint(t[e-1],t[e],Math.PI-i,n,!0),g=getSymetricPoint(t[e-1],t[e],i,n,!1);h.push(o),s.push(g)}return h.concat(s)}function getArrowPoints(t,e,i,n){let r=getMid(t,e),o=getDistance(r,i),c=getSymetricPoint(i,r,0,.3*o,!0),g=getSymetricPoint(i,r,0,.5*o,!0);c=getSymetricPoint(r,c,HALF_PI,o/5,n),g=getSymetricPoint(r,g,HALF_PI,o/4,n);let a=[r,c,g,i],P=getArrowHeadPoints(a,headHeightFactor,headWidthFactor,neckHeightFactor,neckWidthFactor),h=P[0],s=P[4],l=getDistance(t,e)/getBaseLength(a)/2,u=getArrowBodyPoints(a,h,s,l),A=u.length,m=u.slice(0,A/2),M=u.slice(A/2,A);return m.push(h),M.push(s),m=m.reverse(),m.push(e),M=M.reverse(),M.push(t),m.reverse().concat(P,M)}function getBezierPoints(t){if(t.length<=2)return t;let e=[],i=t.length-1;for(let n=0;n<=1;n+=.01){let r=0,o=0;for(let e=0;e<=i;e++){let c=getBinomialFactor(i,e),g=Math.pow(n,e),a=Math.pow(1-n,i-e);r+=c*g*a*t[e][0],o+=c*g*a*t[e][1]}e.push([r,o])}return e.push(t[i]),e}function getBinomialFactor(t,e){return getFactorial(t)/(getFactorial(e)*getFactorial(t-e))}function getFactorial(t){if(t<=1)return 1;if(2==t)return 2;if(3==t)return 6;if(4==t)return 24;if(5==t)return 120;let e=1;for(let i=1;i<=t;i++)e*=i;return e}function isClockWise(t,e,i){return(i[1]-t[1])*(e[0]-t[0])>(e[1]-t[1])*(i[0]-t[0])}const headHeightFactor=.25,headWidthFactor=.3,neckHeightFactor=.85,neckWidthFactor=.15,TWO_PI=2*Math.PI,HALF_PI=Math.PI/2;export function CreateDoubleArrow(t){let e=t.doubleArrowPoint1,i=t.doubleArrowPoint2,n=t.doubleArrowPoint3,r=t.doubleArrowPoint4?t.doubleArrowPoint4:t.movePoint;null==t.minPoint&&(t.minPoint=getMid(e,i));let o,c,g=t.minPoint,a=calculateSymmetryPoint(e,i,n||r);isClockWise(e,i,r)?n?(o=getArrowPoints(e,g,r,!1),c=getArrowPoints(g,i,n,!0)):(o=getArrowPoints(e,g,a,!1),c=getArrowPoints(g,i,r,!0)):n?(o=getArrowPoints(i,g,n,!1),c=getArrowPoints(g,e,r,!0)):(o=getArrowPoints(i,g,r,!1),c=getArrowPoints(g,e,a,!0));let P=o.length,h=(P-5)/2,s=o.slice(0,h),l=o.slice(h,h+5),u=o.slice(h+5,P),A=c.slice(0,h),m=c.slice(h,h+5),M=c.slice(h+5,P);A=getBezierPoints(A);let F=getBezierPoints(M.concat(s.slice(1)));u=getBezierPoints(u);let I=A.concat(m,F,l,u);return[I]}

 DrawDoubleArrow.js

import{CreateDoubleArrow}from"./CreateDoubleArrow.js";const doubleClickZoom={enable:e=>{setTimeout(()=>{e.map&&e.map.doubleClickZoom&&e._ctx&&e._ctx.store&&e._ctx.store.getInitialConfigValue&&e._ctx.store.getInitialConfigValue("doubleClickZoom")&&e.map.doubleClickZoom.enable()},0)},disable(e){setTimeout(()=>{e.map&&e.map.doubleClickZoom&&e.map.doubleClickZoom.disable()},0)}},DrawDoubleArrow={onSetup:function(e){const o=this.newFeature({type:"Feature",properties:{isDoubleArrow:!0},geometry:{type:"Polygon",coordinates:[[]]}});return this.addFeature(o),this.clearSelectedFeatures(),doubleClickZoom.disable(this),this.updateUIClasses({mouse:"add"}),this.setActionableState({trash:!0}),{doubleArrow:o,currentVertexPosition:0}},onTap:function(e,o){e.doubleArrow.properties.doubleArrowPoint1&&this.onMouseMove(e,o),this.onClick(e,o)},onKeyUp:function(e,o){if(27===o.keyCode)return this.changeMode("simple_select")},onTrash:function(e){this.deleteFeature([e.doubleArrow.id],{silent:!0}),this.changeMode("simple_select")},onStop:function(e){doubleClickZoom.enable(this),this.updateUIClasses({mouse:"none"}),this.activateUIButton(),void 0!==this.getFeature(e.doubleArrow.id)&&(e.doubleArrow.removeCoordinate("0.4"),e.doubleArrow.isValid()?this.map.fire("draw.create",{features:[e.doubleArrow.toGeoJSON()]}):(this.deleteFeature([e.doubleArrow.id],{silent:!0}),this.changeMode("simple_select",{},{silent:!0})))},onClick:function(e,o){if(e.doubleArrow.updateCoordinate(`0.${e.currentVertexPosition}`,o.lngLat.lng,o.lngLat.lat),e.currentVertexPosition++,e.doubleArrow.properties["doubleArrowPoint"+e.currentVertexPosition]=[o.lngLat.lng,o.lngLat.lat],this.updateUIClasses({mouse:"add"}),e.doubleArrow.updateCoordinate(`0.${e.currentVertexPosition}`,o.lngLat.lng,o.lngLat.lat),e.doubleArrow.properties.doubleArrowPoint2&&e.doubleArrow.properties.doubleArrowPoint3){let o=CreateDoubleArrow(e.doubleArrow.properties);e.doubleArrow.incomingCoords(o)}4==e.currentVertexPosition&&(this.updateUIClasses({mouse:"pointer"}),this.changeMode("simple_select",{featuresId:e.doubleArrow.id}))},onMouseMove:function(e,o){if(e.doubleArrow.properties.doubleArrowPoint1&&(e.doubleArrow.properties.doubleArrowPoint2||e.doubleArrow.updateCoordinate(`0.${e.currentVertexPosition}`,o.lngLat.lng,o.lngLat.lat),e.doubleArrow.properties.movePoint=[o.lngLat.lng,o.lngLat.lat],e.doubleArrow.properties.doubleArrowPoint2)){let o=CreateDoubleArrow(e.doubleArrow.properties);e.doubleArrow.incomingCoords(o)}},toDisplayFeatures:function(e,o,r){const t=o.properties.id===e.doubleArrow.id;if(o.properties.active=t?"true":"false",!t)return r(o);if(0===o.geometry.coordinates.length)return;if(!e.doubleArrow.properties.doubleArrowPoint1)return;e.doubleArrow.properties.doubleArrowPoint1&&r(this.createVertex(e.doubleArrow.id,e.doubleArrow.properties.doubleArrowPoint1,"0.0",!1)),e.doubleArrow.properties.doubleArrowPoint2&&r(this.createVertex(e.doubleArrow.id,e.doubleArrow.properties.doubleArrowPoint2,"0.1",!1)),e.doubleArrow.properties.doubleArrowPoint3&&r(this.createVertex(e.doubleArrow.id,e.doubleArrow.properties.doubleArrowPoint3,"0.2",!1)),e.doubleArrow.properties.doubleArrowPoint4&&r(this.createVertex(e.doubleArrow.id,e.doubleArrow.properties.doubleArrowPoint4,"0.3",!1)),e.doubleArrow.properties.minPoint&&r(this.createVertex(e.doubleArrow.id,e.doubleArrow.properties.minPoint,"0.4",!1));const i=o.geometry.coordinates[0].length;if(3==i||4==i&&e.doubleArrow.properties.movePoint[0]==e.doubleArrow.properties.doubleArrowPoint2[0]&&e.doubleArrow.properties.movePoint[1]==e.doubleArrow.properties.doubleArrowPoint2[1]){const e=[[o.geometry.coordinates[0][0][0],o.geometry.coordinates[0][0][1]],[o.geometry.coordinates[0][1][0],o.geometry.coordinates[0][1][1]]];r({type:"Feature",properties:o.properties,geometry:{coordinates:e,type:"LineString"}})}return r(o)},createVertex:function(e,o,r,t){return{type:"Feature",properties:{meta:"vertex",parent:e,coord_path:r,active:t?"true":"false"},geometry:{type:"Point",coordinates:o}}}};export default DrawDoubleArrow;

使用方法 

// 双箭头
import DrawDoubleArrow from "./DrawDoubleArrow";

let modes = MapboxDraw.modes;     
modes.draw_double_arrow = DrawDoubleArrow;
this.draw.changeMode(“draw_double_arrow”);

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

侧耳倾听...

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值