| 1 |
- !function(e){class t{constructor(e,t={}){const r=this;r.map=e,r.onEditComplete=t.onEditComplete||null,r.tempData=null,r.tempSource=null,r.tempPoints=[],r.drawType="",r.isDrawing=!1,r.hoveredPolygonId=null,r.tempLineSource=null,r.itemId="",r.totalDistance=0,r.drawMarkers=[],r.moveMarkerTips=null,r.lastClickTime=0,r.clickTimer=null,r.clickCount=0,r.mouseDownPos=null,r.isDragWhole=!1,r.lastLngLat=null,r.isEditMode=!1,r.isEditFlag=!1,r.selectedFeature=null,r.selectedFeatureId="",r.layersIds=[],r.editMarkers=[],r.isDragging=!1,r.draggingPointIndex=-1,r.dragEventHandlers=null,r.dragEventDrawHandlers=null,r.unit="kilometers",r.unitLabel="km",r.editLayerIds=[],r._mapClickHandle=null,r._mapDblClickHandle=null,r._mapMouseDownHandle=null,r._mapMouseMoveHandle=null,r._mapMouseUpHandle=null,r.loadDrawLayer(),r.bindMapEvents()}getCompleteFeature(e){const t=this;let r=JSON.parse(JSON.stringify(e));delete r.properties.drawType,delete r.properties.isCircle,t.onEditComplete&&t.onEditComplete({type:"Feature",geometry:r.geometry,properties:r.properties||{}})}bindMapEvents(){const e=this;e._mapClickHandle&&e.map.off("click",e._mapClickHandle),e._mapDblClickHandle&&e.map.off("dblclick",e._mapDblClickHandle),e._mapMouseDownHandle&&e.map.off("mousedown",e._mapMouseDownHandle),e._mapMouseMoveHandle&&e.map.off("mousemove",e._mapMouseMoveHandle),e._mapMouseUpHandle&&e.map.off("mouseup",e._mapMouseUpHandle),e._mapClickHandle=null,e._mapDblClickHandle=null,e._mapMouseDownHandle=null,e._mapMouseMoveHandle=null,e._mapMouseUpHandle=null,e.initMapEditEvents(),e._mapClickHandle=t=>{if(e.handleFeatureClick(t),e.isEditMode){const r=Date.now(),a=300;clearTimeout(e.clickTimer),r-e.lastClickTime>a?(e.clickCount=1,e.lastClickTime=r,e.clickTimer=setTimeout(()=>{1===e.clickCount&&e.handleMapClick(t),e.clickCount=0},10)):(e.clickCount=2,e.lastClickTime=0)}},e.map.on("click",e._mapClickHandle),e._mapDblClickHandle=t=>{clearTimeout(e.clickTimer),e.clickCount=0,e.lastClickTime=0,e.handleMapDblClick(t)},e.map.on("dblclick",e._mapDblClickHandle),e.bindDeleteHotkey()}initMapEditEvents(){const e=this;e._mapMouseDownHandle=t=>{e.selectedFeature&&"distance"!==e.selectedFeature.properties.drawType&&"area"!==e.selectedFeature.properties.drawType&&(e.mouseDownPos=t.point,e.lastLngLat=t.lngLat,e.isDragging=!1,t.preventDefault(),e.map.getCanvas().style.cursor="grabbing")},e.map.on("mousedown",e._mapMouseDownHandle),e._mapMouseMoveHandle=t=>{if(!e.selectedFeature)return;if((e.isEditMode||e.isEditFlag)&&e.isDragging&&(e.map.getCanvas().style.cursor="move",e.handleDrag(t)),!e.mouseDownPos||!e.selectedFeature)return;if("distance"===e.selectedFeature.properties.drawType||"area"===e.selectedFeature.properties.drawType)return;e.draggingPointIndex=-1;const r=Math.abs(t.point.x-e.mouseDownPos.x),a=Math.abs(t.point.y-e.mouseDownPos.y);if(r>1||a>1){e.isDragging=!0;const r=t.lngLat,a=r.lng-e.lastLngLat.lng,i=r.lat-e.lastLngLat.lat;e.clearEditMarkers(),e.moveWholeFeature(a,i),e.lastLngLat=r}},e.map.on("mousemove",e._mapMouseMoveHandle),e._mapMouseUpHandle=()=>{e.selectedFeature&&(e.mouseDownPos=null,e.isDragging?(e.getCompleteFeature(e.selectedFeature),"distance"===e.selectedFeature.properties.drawType||"area"===e.selectedFeature.properties.drawType?e.clearEditMarkers():e.showEditMarkers()):e.clearEditMarkers(),e.isDragging=!1,e.tempLineSource.setData({type:"FeatureCollection",features:[]}),e.map.getCanvas().style.cursor="")},e.map.on("mouseup",e._mapMouseUpHandle)}loadDrawLayer(){const e=this;e.map.getSource("temp-line")||(e.map.addSource("temp-line",{type:"geojson",data:{type:"FeatureCollection",features:[]}}),e.map.addLayer({id:"temp-line-layer",type:"line",source:"temp-line",paint:{"line-color":"red","line-width":2,"line-dasharray":[3,3]}})),e.tempLineSource=e.map.getSource("temp-line"),e.map.on("mousemove",t=>{if(!e.isDrawing)return;if(e.moveMarkerTips)e.moveMarkerTips.setLngLat(t.lngLat);else{let r="鼠标双击完成";"circle"!==e.drawType&&"rectangle"!==e.drawType||(r="鼠标双击/单击完成"),e.addMoveMarkerTips(t.lngLat,r)}const r=[t.lngLat.lng,t.lngLat.lat];if("rectangle"===e.drawType){if(e.tempPoints.length<1)return;const t=[Math.min(e.tempPoints[0][0],r[0]),Math.min(e.tempPoints[0][1],r[1]),Math.max(e.tempPoints[0][0],r[0]),Math.max(e.tempPoints[0][1],r[1])];e.addToMap(turf.bboxPolygon(t))}else if("circle"===e.drawType&&e.tempPoints.length>=1){let t=e.tempPoints[0],a=turf.distance(turf.point(t),turf.point(r),{units:"kilometers"});e.addToMap(turf.circle(t,a,64))}if(e.tempPoints.length<1||"rectangle"===e.drawType)return;const a=[t.lngLat.lng,t.lngLat.lat],i=e.tempPoints[e.tempPoints.length-1],s=turf.lineString([i,a]);e.tempLineSource.setData(s)})}startDraw(e,t,r){const a=this;a.drawType=e,a.isDrawing=!0,a.tempPoints=[],a.tempLineSource.setData({type:"FeatureCollection",features:[]}),a.itemId="draw-"+Date.now(),a.map.getCanvas().style.cursor="crosshair",a.totalDistance=0,a.unit=r||"kilometers",a.unitLabel="kilometers"===a.unit?"km":"m",t=t||!0,a.isEditDrawTool(t)}isEditDrawTool(e){const t=this;t.isEditMode=e,t.isEditMode||(t.clearEditMarkers(),t.selectedFeature=null,t.selectedFeatureId="",t.layersIds=[])}isEdit(e){const t=this;t.isEditFlag=e,t.isEditFlag||(t.clearEditMarkers(),t.selectedFeature=null,t.selectedFeatureId="",t.layersIds=[])}handleMapClick(e){const t=this;if(!t.isDrawing)return;const r=[e.lngLat.lng,e.lngLat.lat];if(t.tempPoints.push(r),"point"===t.drawType){let e=turf.point(r);e.properties.drawType="point",e.properties.isCircle=!1,t.addToMap(e),t.finishDraw()}if("line"===t.drawType&&t.tempPoints.length>=2){let e=turf.lineString(t.tempPoints);e.properties.drawType="line",e.properties.isCircle=!1,t.addToMap(e)}if("polygon"===t.drawType&&t.tempPoints.length>=2)if(t.tempPoints.length>=3){let e=turf.polygon([[...t.tempPoints,t.tempPoints[0]]]);e.properties.drawType="polygon",e.properties.isCircle=!1,t.addToMap(e)}else{let e=turf.lineString(t.tempPoints);e.properties.drawType="polygon",e.properties.isCircle=!1,t.addToMap(e)}if("circle"===t.drawType&&t.tempPoints.length>=2){const e=t.tempPoints[0],r=turf.distance(turf.point(e),turf.point(t.tempPoints[1]),{units:t.unit});let a=turf.circle(e,r,64);a.properties.drawType="circle",a.properties.isCircle=!0,t.addToMap(a),t.finishDraw()}if("distance"===t.drawType&&t.tempPoints.length>=2){let r=turf.lineString(t.tempPoints);r.properties.drawType="distance",r.properties.isCircle=!1,t.addToMap(r);const a=turf.distance(turf.point(t.tempPoints[0]),turf.point(t.tempPoints[1]),{units:t.unit});t.totalDistance+=a,t.addMarker(e.lngLat,t.totalDistance.toFixed(2)+" "+t.unitLabel)}if("area"===t.drawType&&t.tempPoints.length>=2)if(t.tempPoints.length>=3){let e=turf.polygon([[...t.tempPoints,t.tempPoints[0]]]);e.properties.drawType="area",e.properties.isCircle=!1,t.addToMap(e);const r=turf.area(e);t.totalDistance+=r}else{let e=turf.lineString(t.tempPoints);e.properties.drawType="area",e.properties.isCircle=!1,t.addToMap(e)}"rectangle"===t.drawType&&t.tempPoints.length>=2&&t.finishDraw(),t.updateTempLayer()}handleMapDblClick(e){const t=this;if(t.isDrawing&&"point"!==t.drawType){if("area"===t.drawType&&t.tempPoints.length>=2)if(t.tempPoints.length>=3){let r=turf.polygon([[...t.tempPoints,t.tempPoints[0]]]);r.properties.drawType="area",r.properties.isCircle=!1,t.addToMap(r);const a=(turf.area(r)/1e6).toFixed(2);t.addMarker(e.lngLat,a+" 平方公里")}else{let r=turf.lineString(t.tempPoints);r.properties.drawType="area",r.properties.isCircle=!1,t.addToMap(r);const a=turf.distance(turf.point(t.tempPoints[0]),turf.point(t.tempPoints[1]),{units:t.unit});t.totalDistance+=a,t.addMarker(e.lngLat,t.totalDistance.toFixed(2)+" "+t.unitLabel)}t.finishDraw()}}updateTempLayer(){const e=this;let t;"point"===e.drawType&&e.tempPoints.length?t=turf.point(e.tempPoints[0]):"line"===e.drawType&&e.tempPoints.length>=2?t=turf.lineString(e.tempPoints):"polygon"===e.drawType&&e.tempPoints.length>=2?t=turf.lineString([...e.tempPoints,e.tempPoints[0]]):"circle"===e.drawType&&e.tempPoints.length>=1?t=turf.point(e.tempPoints[0]):"distance"===e.drawType&&e.tempPoints.length>=2?t=turf.lineString(e.tempPoints):"area"===e.drawType&&e.tempPoints.length>=2&&(t=turf.lineString([...e.tempPoints,e.tempPoints[0]])),e.tempSource?.setData(t||{type:"FeatureCollection",features:[]})}addMoveMarkerTips(e,t){let r=document.createElement("div");r.className="marker-label-tips",r.innerText=t,this.moveMarkerTips=new mapboxgl.Marker(r,{anchor:"center",offset:[0,-30]}).setLngLat(e).addTo(this.map)}addMarker(e,t){let r=document.createElement("div");r.className="marker-label-tips",r.innerText=t;let a=new mapboxgl.Marker(r,{anchor:"center"}).setLngLat(e).addTo(this.map);this.drawMarkers.push(a)}addEditMarker(e,t){const r=this;let a=document.createElement("div");a.className="edit-marker",a.style.width="10px",a.style.height="10px",a.style.borderRadius="50%",a.style.backgroundColor="red",a.style.border="2px solid white",a.style.cursor="pointer",a.addEventListener("mousedown",e=>{e.stopPropagation(),r.isDragging=!0,r.draggingPointIndex=t,r.map.getCanvas().style.cursor="grabbing"});let i=new mapboxgl.Marker(a).setLngLat(e).addTo(r.map);r.editMarkers.push(i),r.selectedFeature.properties.isCircle||r.insertTwoMiddlePoints(i,t)}clearNodeMarkers(){this.drawMarkers.forEach(e=>e.remove()),this.drawMarkers=[]}clearEditMarkers(){this.editMarkers.forEach(e=>e.remove()),this.editMarkers=[]}showEditMarkers(){const e=this;if(!e.selectedFeature)return;const t=e.selectedFeature;"Feature"===t.type&&("Point"===t.geometry.type?e.addEditMarker(t.geometry.coordinates,0):"LineString"===t.geometry.type?t.geometry.coordinates.forEach((t,r)=>{e.addEditMarker(t,r)}):"Polygon"===t.geometry.type&&t.geometry.coordinates[0].forEach((r,a)=>{a!=t.geometry.coordinates[0].length-1&&e.addEditMarker(r,a)}))}clearAll(){const e=this;e.clearNodeMarkers(),e.clearEditMarkers(),e.selectedFeature=null,e.selectedFeatureId="",e.layersIds=[];const t=e.map.getStyle().layers;t.sort((e,t)=>e.type.localeCompare(t.type)),t.forEach(t=>{if(t.id.startsWith("draw-")){if(-1!==t.id.indexOf("-point")&&e.map.removeLayer(t.id),-1!==t.id.indexOf("-line")){e.map.removeLayer(t.id);let r=t.id.replace("-line","");e.map.removeSource(r)}-1!==t.id.indexOf("-polygon")&&e.map.removeLayer(t.id)}})}addToMap(e){const t=this;let r=t.itemId;t.map.getSource(r)?(t.map.getSource(r).setData(e),t.tempPoints.length>=3&&("area"===t.drawType||"polygon"===t.drawType)&&(t.map.getLayer(r+"-polygon")||t.map.addLayer({id:r+"-polygon",type:"fill",source:r,paint:{"fill-color":"red","fill-opacity":.3}}))):(t.map.addSource(r,{type:"geojson",data:e}),"line"===t.drawType?t.map.addLayer({id:r+"-line",type:"line",source:r,paint:{"line-color":"red","line-width":2}}):"polygon"===t.drawType?(t.tempPoints.length>=3&&t.map.addLayer({id:r+"-polygon",type:"fill",source:r,paint:{"fill-color":"red","fill-opacity":.3}}),t.map.addLayer({id:r+"-line",type:"line",source:r,paint:{"line-color":"red","line-width":2}})):"circle"===t.drawType?(t.map.addLayer({id:r+"-polygon",type:"fill",source:r,paint:{"fill-color":"red","fill-opacity":.3}}),t.map.addLayer({id:r+"-line",type:"line",source:r,paint:{"line-color":"red","line-width":2}})):"distance"===t.drawType?t.map.addLayer({id:r+"-line",type:"line",source:r,paint:{"line-color":"red","line-width":2}}):"area"===t.drawType?(t.tempPoints.length>=3&&t.map.addLayer({id:r+"-polygon",type:"fill",source:r,paint:{"fill-color":"red","fill-opacity":.3}}),t.map.addLayer({id:r+"-line",type:"line",source:r,paint:{"line-color":"red","line-width":2}})):"rectangle"===t.drawType?(t.map.addLayer({id:r+"-polygon",type:"fill",source:r,paint:{"fill-color":"red","fill-opacity":.3}}),t.map.addLayer({id:r+"-line",type:"line",source:r,paint:{"line-color":"red","line-width":2}})):t.map.addLayer({id:r+"-point",type:"circle",source:r,paint:{"circle-radius":5,"circle-color":"red"}})),t.tempData=e}finishDraw(){const e=this;e.getCompleteFeature(e.tempData),e.isDrawing=!1,e.drawType="",e.tempPoints=[],e.tempSource?.setData({type:"FeatureCollection",features:[]}),e.tempLineSource.setData({type:"FeatureCollection",features:[]}),e.map.getCanvas().style.cursor="",e.moveMarkerTips&&(e.moveMarkerTips.remove(),e.moveMarkerTips=null)}handleFeatureClick(e){const t=this,r=t.map.getStyle().layers.filter(e=>e.id.startsWith("draw-")).map(e=>e.id),a=e.point,i=[[a.x-5,a.y-5],[a.x+5,a.y+5]];t.editLayerIds.forEach(e=>{r.push(e)});const s=t.map.queryRenderedFeatures(i,{layers:r});if(s.length>0)if(t.isEditFlag){const e=s[0],r=e.layer.source;if(!t.map.getSource(r))return;t.selectedFeatureId=r;const a=t.map.getSource(r)._data;if(a.geometry?t.selectedFeature=JSON.parse(JSON.stringify(a)):a.features.forEach(r=>{r.properties.dms_id!==e.properties.dms_id||(t.selectedFeature=JSON.parse(JSON.stringify(r)))}),t.getCompleteFeature(t.selectedFeature),t.clearEditMarkers(),"distance"===t.selectedFeature.properties.drawType||"area"===t.selectedFeature.properties.drawType)return;t.showEditMarkers()}else{const e=s[0].layer.id.split("-").slice(0,-1).join("-");if(!t.map.getSource(e))return;t.selectedFeatureId=e;const r=t.map.getSource(e)._data;if(t.selectedFeature=JSON.parse(JSON.stringify(r)),t.clearEditMarkers(),"distance"===t.selectedFeature.properties.drawType||"area"===t.selectedFeature.properties.drawType)return;t.showEditMarkers()}else t.clearEditMarkers(),t.selectedFeature=null,t.selectedFeatureId=""}handleEditDrawClick(e){const t=this,r=e.point,a=[[r.x-5,r.y-5],[r.x+5,r.y+5]],i=t.map.queryRenderedFeatures(a,{layers:t.editLayerIds});if(i.length>0){const e=i[0],r=e.layer.source;if(!t.map.getSource(r))return;t.selectedFeatureId=r;const a=t.map.getSource(r)._data;a.geometry?t.selectedFeature=JSON.parse(JSON.stringify(a)):a.features.forEach(r=>{r.properties.dms_id!==e.properties.dms_id||(t.selectedFeature=JSON.parse(JSON.stringify(r)))}),t.getCompleteFeature(t.selectedFeature),t.clearEditMarkers(),t.showEditMarkers()}else t.selectedFeature=null,t.selectedFeatureId=""}moveWholeFeature(e,t){const r=this;if(!r.selectedFeature)return;const a=r.selectedFeature;if("Point"===a.geometry.type)a.geometry.coordinates[0]+=e,a.geometry.coordinates[1]+=t;else if("LineString"===a.geometry.type)a.geometry.coordinates.forEach(r=>{r[0]+=e,r[1]+=t});else if("Polygon"===a.geometry.type)if(a.properties.isCircle){const i=turf.centroid(a).geometry.coordinates,s=[i[0]+e,i[1]+t],n=turf.distance(i,a.geometry.coordinates[0][0],{units:"meters"}),o=turf.circle(s,n,{units:"meters",steps:64});o.properties=a.properties,r.selectedFeature=o}else a.geometry.coordinates.forEach(r=>{r.forEach(r=>{r[0]+=e,r[1]+=t})});r.map.getSource(r.selectedFeatureId).setData(r.selectedFeature);const i=r.map.getSource(r.selectedFeatureId)._data;r.selectedFeature=JSON.parse(JSON.stringify(i))}editCircleVertex(e){const t=this,r=t.selectedFeature,a=turf.centroid(r).geometry.coordinates,i=turf.distance(a,e,{units:"meters"});if(i<5)return;const s=turf.circle(a,i,{units:"meters",steps:64});s.properties=r.properties;const n=turf.lineString([a,e]);return t.tempLineSource.setData(n),t.selectedFeature=s,s}insertTwoMiddlePoints(e,t){const r=this;e.getElement().addEventListener("click",e=>{if(e.stopPropagation(),!r.selectedFeature)return;const a=r.selectedFeature.geometry;let i=[],s=!1;if("LineString"===a.type?i=[...a.coordinates]:"Polygon"===a.type&&(i=[...a.coordinates[0]],s=!0),!(i.length<2)){if(s){let e=i.slice(0,-1);const r=e.length;let s=t;t===i.length-1&&(s=0);const n=(s+1)%r,o=e[(s-1+r)%r],l=e[s],d=e[n],p=[(o[0]+l[0])/2,(o[1]+l[1])/2],c=[(l[0]+d[0])/2,(l[1]+d[1])/2];e.splice(s,0,p),e.splice(s+2,0,c),i=[...e,e[0]],a.coordinates[0]=i}else{if(0===t){const e=i[t+1],r=[(i[t][0]+e[0])/2,(i[t][1]+e[1])/2];i.splice(t+1,0,r)}else if(t===i.length-1){const e=i[t-1],r=[(e[0]+i[t][0])/2,(e[1]+i[t][1])/2];i.splice(t,0,r)}else{const e=i[t-1],r=i[t+1],a=i[t],s=[(e[0]+a[0])/2,(e[1]+a[1])/2],n=[(a[0]+r[0])/2,(a[1]+r[1])/2];i.splice(t,0,s),i.splice(t+2,0,n)}a.coordinates=i}r.refreshFeature()}})}bindDeleteHotkey(){const t=this;e.removeEventListener("keydown",t._deleteKeyHandler),t._deleteKeyHandler=function(e){"Delete"===e.key&&t.selectedFeature&&(t.isEditMode||t.isEditFlag)&&(e.preventDefault(),-1!==t.draggingPointIndex&&t.deleteVertex(t.draggingPointIndex))},e.addEventListener("keydown",t._deleteKeyHandler)}deleteVertex(e){const t=this;if(!t.selectedFeature)return;const r=t.selectedFeature.geometry;let a,i=!1;if(t.draggingPointIndex=-1,t.isDragging=!1,"LineString"===r.type){if(a=r.coordinates,a.length<=2)return}else if("Polygon"===r.type&&(i=!0,a=r.coordinates[0],a.length<=4))return;a.splice(e,1),i&&0===e&&(a[a.length-1]=a[0]),t.refreshFeature()}refreshFeature(){const e=this;e.selectedFeature&&e.selectedFeatureId&&(e.draggingPointIndex=-1,e.isDragging=!1,e.map.getSource(e.selectedFeatureId).setData(e.selectedFeature),e.selectedFeature=JSON.parse(JSON.stringify(e.map.getSource(e.selectedFeatureId)._data)),e.clearEditMarkers(),e.showEditMarkers())}handleDrag(e){const t=this;if(!t.selectedFeature||-1===t.draggingPointIndex)return;if("distance"===t.selectedFeature.properties.drawType||"area"===t.selectedFeature.properties.drawType)return;let r=t.selectedFeature,a=[e.lngLat.lng,e.lngLat.lat];t.selectedFeature.properties.isCircle?(t.clearEditMarkers(),r=t.editCircleVertex(a)):("Point"===r.geometry.type?r.geometry.coordinates=a:"LineString"===r.geometry.type?r.geometry.coordinates[t.draggingPointIndex]=a:"Polygon"===r.geometry.type&&(r.geometry.coordinates[0][t.draggingPointIndex]=a,0===t.draggingPointIndex&&(r.geometry.coordinates[0][r.geometry.coordinates[0].length-1]=a)),t.clearEditMarkers(),t.showEditMarkers()),t.selectedFeature=JSON.parse(JSON.stringify(r)),t.map.getSource(t.selectedFeatureId).setData(r),t.getCompleteFeature(t.selectedFeature)}setEditLayerIds(e){this.editLayerIds=e}deleteSelected(){let t=this;if(!t.selectedFeatureId)return;e.mapboxMap.getStyle().layers.forEach(e=>{e.id.startsWith(t.selectedFeatureId)&&t.map.removeLayer(e.id)}),t.map.removeSource(t.selectedFeatureId),t.clearEditMarkers(),t.selectedFeature=null,t.selectedFeatureId="",t.layersIds=[]}}e.MapDraw={init:function(e,r){const a=new t(e,r);return{startDraw:(e,t,r)=>a.startDraw(e,t,r),isEdit:e=>a.isEdit(e),clearAll:()=>a.clearAll(),setEditLayerIds:e=>a.setEditLayerIds(e)}}}}(window);
|