关于leaflet:leaflet底图样式修改及热力图加载地图打点

<!DOCTYPE html><html><head><meta charset="UTF-8"><title data-i18n="resources.title_heatMap"></title><!-- <script type="text/javascript" include="randomcolor" src="./js/include-web.js"></script> --> <style> #heatNumbers, #heatRadius { width: 50px; display: inline-block; } </style> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.5.1/leaflet.css" /> <link rel="stylesheet" href="https://iclient.supermap.io/dist/leaflet/iclient-leaflet.min.css" /> <link rel="stylesheet" href="./css/MarkerCluster.Default.css" /> <link rel="stylesheet" href="./css/MarkerCluster.css" /> <script type="text/javascript" src="./js/jquery.min.js"> </script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.5.1/leaflet.js"></script> <script type="text/javascript" src="https://iclient.supermap.io/dist/leaflet/iclient-leaflet.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/heatmap.js/2.0.2/heatmap.js"></script> <!-- 应用new HeatmapOverlay --> <script src="./js/leaflet-heatmap.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.heat/0.2.0/leaflet-heat.js"></script> <!--引入proj4,百度地图用--> <script src="./proj4/proj4.js"></script> <script src="./proj4/proj4leaflet.min.js"></script> <!-- 加载高德地图 --> <script src="./js/leaflet.ChineseTmsProviders.js"></script> <!-- 互联网地图纠偏插件 需配合 leaflet.ChineseTmsProviders.js 插件应用 无需js代码,援用后主动纠偏 纠偏后的坐标为WGS84 --> <script src="./js/leaflet.mapCorrection.min.js"></script> <!-- 点聚合 --> <script src="./js/leaflet.markercluster-src.js"></script><script src="./js/data.js"></script><!-- 批改地图款式 --><script src="./js/leaflet-tilelayer-colorizr.js"></script><style> .leaflet-zoom-animated img { -webkit-filter: invert(50%) grayscale(0.5) saturate(0.5) brightness(1.6) opacity(1) hue-rotate(334deg) sepia(10%) !important; -ms-filter: invert(1) grayscale(0.5) saturate(0.5) brightness(1.6) opacity(1) hue-rotate(334deg) sepia(10%) !important; -moz-filter: invert(1) grayscale(0.5) saturate(0.5) brightness(1.6) opacity(1) hue-rotate(334deg) sepia(10%) !important; filter: invert(1) grayscale(0.5) saturate(0.5) brightness(1.6) opacity(1) hue-rotate(334deg) sepia(1%) !important; }</style></head><body style=" margin: 0;overflow: hidden;background: #fff;width: 100%;height:100%;position: absolute;top: 0;"><div id="map" style="margin:0 auto;width: 100%;height: 100%"></div><script type="text/javascript"> var map, resultLayer,normal,image,baseLayers; var mapMarkers = []; var markers; addGaodeLayer() map = L.map('map', { preferCanvas: true, center: [34.342329669, 109.000431666], layers: [normal], maxZoom: 20, zoom: 12 }); // http://192.168.0.105:9090/img/{z}/{x}/{y}.png // 这个是瓦片地图的地址 L.tileLayer.colorizr("http://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}", { maxZoom: 18, minZoom: 3, colorize: function (pixel) { // 这个办法用来调整所有的图片上的rgb值,pixel是图片原有的rgb值 pixel.r += 13; pixel.g += 97; pixel.b += 190; return pixel; } }).addTo(map); // L.control.layers(baseLayers, null).addTo(map); loadHeatMap(); function getIcon(type){ var defaultIcon = L.icon({ iconUrl: '../src/assets/IC/maker1_gif.webp', iconSize: [40, 40], // 图标的大小 【值1,值2】 为具体你自定义图标的尺寸,比方我图标尺寸是32×52,示意该图标:宽度32像素,高度:52像素,那么值1:就是32,值2:就是52 iconAnchor: [20, 20], // 图标将对应标记点的地位 这个是重点, 【值1,值2】,值1:为图标坐标第一个值(即32)的一半,值2:为图标坐标第二个值(即52) }); return defaultIcon } function loadHeatMap() { var cfg = { max: 50, radius: 14, // scaleRadius: true, //设置热力点是否平滑过渡 // useLocalExtrema: true, //应用部分极值 blur: 0.95, //系数越高,突变越平滑,默认是0.85 latField: 'lat', lngField: 'lng', //经度 valueField: 'count', //热力点的值 minOpacity: 0.5, gradient: { 0.5: 'blue', // [0,0.9) 0.925: 'skyblue', // [0.9,0.93) 0.99: 'green', 0.9950: '#ffea00', 0.995551: 'orange', 1.0: 'red' } } var heatPoints = makerData resultLayer = new HeatmapOverlay(cfg); console.log('heatPoints==', heatPoints) // resultLayer = L.heatLayer(heatPoints, cfg).addTo(map); resultLayer.setData({ max:50, data: heatPoints }); map.addLayer(resultLayer); // 打点测试 setMakers(makerData) } function addGaodeLayer(){ var normalm = L.tileLayer.chinaProvider('GaoDe.Normal.Map', { maxZoom: 18, minZoom: 5 }); var imgm = L.tileLayer.chinaProvider('GaoDe.Satellite.Map', { maxZoom: 18, minZoom: 5 }); var imga = L.tileLayer.chinaProvider('GaoDe.Satellite.Annotion', { maxZoom: 18, minZoom: 5 }); normal = L.layerGroup([normalm]), image = L.layerGroup([imgm, imga]); baseLayers = { "地图": normal, "影像": image, } } function setMakers(list){ markers = L.markerClusterGroup(); // 标记点位组 for (var i = 0; i < list.length; i++) { var currentItem = list[i]; var title = currentItem.count; var marker = L.marker(new L.LatLng(currentItem.lat, currentItem.lng), { title: '详情', icon :getIcon() }); let showItem = [ { key: '经度', val: currentItem.lng }, { key: '纬度', val: currentItem.lat } ] let basicInfo = '' for (let i = 0; i < showItem.length; i++) { basicInfo += '<div class="info_row"><span class="info_lable">' + showItem[i].key + ':</span>' + showItem[i].val + '</div>' } let myTitle = '<div class="info_title">点位详情</div>' window.basicDom = '<div class="beauty-scroll">' + myTitle + basicInfo + '<div id="map_video_box" class="video_play_block">' + `<div id="play_video_block" style="width:100%;height:99%;"></div>` + '</div>' + '</div>' marker.bindPopup(basicDom); markers.addLayer(marker); } // map.addLayer(markers); // for (var i = 0; i < list.length; i++) { // var a = list[i]; // var data = a // var marker = L.marker(new L.LatLng(a.lat, a.lng), {title: '' , icon :getIcon(a.index)}); // window.currentData = data // marker.bindPopup(basicDom); // 放弃所有弹出窗口关上 // markers.addLayer(marker); // // mapMarkers.push(marker) // } map.addLayer(markers); }</script></body></html>

October 27, 2022 · 3 min · jiezi

关于leaflet:基于leaflet封装的框选四至多边形框选的class类

import L from 'leaflet';import 'leaflet-draw'/*** 案例* async ceju(){* let that = this* const p1 = await new Promise(function(resolve,reject){* let a = new Draw(that.baseMap,that.measureGroup,resolve,reject)* a.rectangle()* }); * console.log(p1);* * }, ***///new的时候须要传入map以及承接的layergroup//返回值的时候须要用异步去承接,所以采纳了promiseclass Draw{ constructor(map,measureGroup,resolve,reject){ this.map = map this.drawDataMap = [] this.stopRectArea = null this.locations = {} this.resolve = resolve this.reject = reject this.measureGroup = measureGroup this.geometry = [] } rectangle(){ let that = this console.log('开始框选'); that.map.off("click") that.map.off("dblclick") that.map.off("dblclick") if(that.stopRectArea != null){ //stopRectArea在data中定义,革除反复的拉框操作 that.map.off('mousedown', that.stopRectArea.mousedown); } var rectangleMeasure = { startPoint: null, endPoint: null, rectangle:null, layer: that.measureGroup, color: "rgba(51,136,255,1)", addRectangle:function(){ rectangleMeasure.destory(); var bounds = []; bounds.push(rectangleMeasure.startPoint); bounds.push(rectangleMeasure.endPoint); rectangleMeasure.rectangle = L.rectangle(bounds, {color: rectangleMeasure.color, weight: 1}); rectangleMeasure.rectangle.addTo(rectangleMeasure.layer); rectangleMeasure.layer.addTo(that.map); }, mousedown: function(e){ rectangleMeasure.rectangle = null; that.map.dragging.disable(); rectangleMeasure.startPoint = e.latlng; that.map.on('mousemove',rectangleMeasure.mousemove) }, mousemove:function(e){ rectangleMeasure.endPoint = e.latlng; rectangleMeasure.addRectangle(); that.map.off('mousedown ', rectangleMeasure.mousedown).on('mouseup', rectangleMeasure.mouseup); }, mouseup: function(){ that.map.dragging.enable(); that.map.off('mousemove',rectangleMeasure.mousemove).off('mouseup', rectangleMeasure.mouseup); that.locations = {}; //locations在data中定义 that.locations['leftX'] = rectangleMeasure.startPoint.lat; that.locations['leftY'] = rectangleMeasure.startPoint.lng; that.locations['rightX'] = rectangleMeasure.endPoint.lat; that.locations['rightY'] = rectangleMeasure.endPoint.lng; that.locations['layer_id'] = rectangleMeasure.layer._leaflet_id; that.locations['layer'] = rectangleMeasure.layer; that.locations['rectangle'] = rectangleMeasure.rectangle; that.drawDataMap.push([rectangleMeasure.startPoint.lat,rectangleMeasure.startPoint.lng]) that.drawDataMap.push([rectangleMeasure.endPoint.lat,rectangleMeasure.startPoint.lng]) that.drawDataMap.push([rectangleMeasure.endPoint.lat,rectangleMeasure.endPoint.lng]) that.drawDataMap.push([rectangleMeasure.startPoint.lat,rectangleMeasure.endPoint.lng]) that.resolve(that.drawDataMap) }, destory:function(){ if(rectangleMeasure.rectangle) rectangleMeasure.layer.removeLayer(rectangleMeasure.rectangle); } }; that.stopRectArea = rectangleMeasure; //记录已点击拉框按钮,未在地图上拉框 that.map.on('mousedown', rectangleMeasure.mousedown); //在地图上拉框 } polygon(){ let that = this that.measureGroup.clearLayers() var points,lines,tempLines,node; that.map.off("mousemove") that.map.off("mousedown") that.map.off("mouseup") function drawPolygon(){ that.map.doubleClickZoom.disable(); lines = new L.polyline([]); tempLines = new L.polyline([],{ dashArray: 5 }); points = []; that.geometry = []; that.map.on('click', onClick); //点击地图 that.map.on('dblclick', onDoubleClick); that.map.on('mousemove', onMove)//双击地图 function onClick(e) { points.push([e.latlng.lat, e.latlng.lng]) lines.addLatLng(e.latlng) that.measureGroup.addLayer(tempLines) that.measureGroup.addLayer(lines) node=L.circle(e.latlng, { color: '#ff0000', fillColor: 'ff0000', fillOpacity: 1 }) that.measureGroup.addLayer(node) that.geometry.push(node) } function onMove(e) { if (points.length > 0) { let ls = [points[points.length - 1], [e.latlng.lat, e.latlng.lng], points[0]] tempLines.setLatLngs(ls) // that.map.addLayer(tempLines) } } function onDoubleClick() { that.geometry.push(L.polygon(points).addTo(that.map)) that.drawDataMap = points that.drawDataMap.splice(that.drawDataMap.length-1,1) points = []; node=null; that.map.off('click', onClick); //点击地图 that.map.off('dblclick', onDoubleClick); that.map.off('mousemove', onMove)//双击地图 that.map.doubleClickZoom.enable(); that.resolve(that.drawDataMap) } } that.removePolygon() drawPolygon() } removePolygon(){ for(let ooo of this.geometry){ ooo.remove(); } }}export default Draw

February 17, 2022 · 2 min · jiezi

关于leaflet:基于leaflet封装测距测面class类

import L from 'leaflet';import 'leaflet-draw'class DrawPlug { constructor(map,measureGroup) { //测距侧面 this.DRAWING = false; //是否正在绘制 this.DRAWLAYERS = []; this.BarDRAWLAYERS = []; this.ISMEASURE = true; //是否是量距 this.MEASURETOOLTIP; //量距提醒 this.MEASUREAREATOOLTIP; //量面提醒 this.MEASURERESULT = 0; //测量后果 this.DRAWPOLYLINE; //绘制的折线 this.DRAWMOVEPOLYLINE; //绘制过程中的折线 this.DRAWPOLYLINEPOINTS = []; //绘制的折线的节点集 this.DRAWPOLYGON; //绘制的面 this.DRAWMOVEPOLYGON; //绘制过程中的面 this.DRAWPOLYGONPOINTS = []; //绘制的面的节点集 this.map = map; this.measureGroup = measureGroup; } startDrawLine() { let that = this that.MEASURERESULT = 0; //测量后果 that.map.getContainer().style.cursor = 'crosshair'; var shapeOptions = { color: '#3388ff', weight: 3, opacity: 0.8, fill: false, clickable: true } that.DRAWPOLYLINE = new L.Polyline([], shapeOptions); //绘制的折线 that.measureGroup.addLayer(that.DRAWPOLYLINE); if (that.ISMEASURE) { //是否是量距 that.MEASURETOOLTIP = new L.Tooltip(that.map); //量距提醒 } that.map.on('mousedown', onClick); that.map.on('dblclick', onDoubleClick); function onClick(e) { console.log('onClick'); that.DRAWING = true; //是否正在绘制 that.DRAWPOLYLINEPOINTS.push(e.latlng); //绘制的折线的节点集 if (that.DRAWPOLYLINEPOINTS.length > 1 && that.ISMEASURE) { //是否是量距 that.MEASURERESULT += e.latlng.distanceTo(that.DRAWPOLYLINEPOINTS[that.DRAWPOLYLINEPOINTS.length - 2]); } that.DRAWPOLYLINE.addLatLng(e.latlng); //绘制的折线 that.map.on('mousemove', onMove); } function onMove(e) { if (that.DRAWING) { //是否正在绘制 if (that.DRAWMOVEPOLYLINE != undefined && that.DRAWMOVEPOLYLINE != null) { //绘制过程中的折线 that.measureGroup.removeLayer(that.DRAWMOVEPOLYLINE); } var prevPoint = that.DRAWPOLYLINEPOINTS[that.DRAWPOLYLINEPOINTS.length - 1]; that.DRAWMOVEPOLYLINE = new L.Polyline([prevPoint, e.latlng], shapeOptions); that.measureGroup.addLayer(that.DRAWMOVEPOLYLINE); if (that.ISMEASURE) { var distance = that.MEASURERESULT + e.latlng.distanceTo(that.DRAWPOLYLINEPOINTS[that.DRAWPOLYLINEPOINTS.length - 1]); console.log(distance); } } } function onDoubleClick(e) { that.map.getContainer().style.cursor = ''; /*显示两点间隔*/ var distance = that.MEASURERESULT + e.latlng.distanceTo(that.DRAWPOLYLINEPOINTS[that.DRAWPOLYLINEPOINTS.length - 1]); var myIcon = L.divIcon({ // html: (distance / 1000).toFixed(2) + "公里", className: 'my-div-icon', html:"<div>"+"<p>"+(distance / 1000).toFixed(2)+"KM</p>"+"</div>", iconSize:26 }); for(let i=0;i<that.DRAWPOLYLINEPOINTS.length-2;i++){ let distance_cust = that.DRAWPOLYLINEPOINTS[i].distanceTo(that.DRAWPOLYLINEPOINTS[i+1]); let myIcon_cust = L.divIcon({ // html: (distance / 1000).toFixed(2) + "公里", className: 'my-div-icon', html:"<div>"+"<p>"+(distance_cust / 1000).toFixed(2)+"KM</p>"+"</div>", iconSize:26 }); let site_c = L.polyline([that.DRAWPOLYLINEPOINTS[i],that.DRAWPOLYLINEPOINTS[i+1]],{color:'rgba(0,0,0,0)',}).addTo(that.measureGroup); let as = site_c.getCenter() let c = new L.Marker(as, { draggable: false,icon: myIcon_cust}); that.measureGroup.addLayer(c) } let marker = new L.Marker(e.latlng, { draggable: false,icon: myIcon}); that.measureGroup.addLayer(marker) if (that.DRAWING) { if (that.DRAWMOVEPOLYLINE != undefined && that.DRAWMOVEPOLYLINE != null) { that.map.removeLayer(that.DRAWMOVEPOLYLINE); that.DRAWMOVEPOLYLINE = null; } that.BarDRAWLAYERS.push(that.DRAWPOLYLINE); that.DRAWPOLYLINEPOINTS = []; that.DRAWING = false; that.ISMEASURE = false; that.map.off('mousedown'); that.map.off('mousemove'); that.map.off('dblclick'); } } } clearLayer(){ let that = this that.measureGroup.clearLayers() } startDrawPolygon() { let that = this that.MEASURERESULT = 0; that.map.getContainer().style.cursor = 'crosshair'; that.map.on('mousedown', function(e) { that.DRAWING = true; that.DRAWPOLYGONPOINTS.push(e.latlng); that.DRAWPOLYGON.addLatLng(e.latlng); }); that.map.on('mousemove', function(e) { if (that.DRAWING) { if (that.DRAWMOVEPOLYGON != undefined && that.DRAWMOVEPOLYGON != null) { that.map.removeLayer(that.DRAWMOVEPOLYGON); } var prevPoint = that.DRAWPOLYGONPOINTS[that.DRAWPOLYGONPOINTS.length - 1]; var firstPoint = that.DRAWPOLYGONPOINTS[0]; that.DRAWMOVEPOLYGON = new L.Polygon([firstPoint, prevPoint, e.latlng], shapeOptions); that.measureGroup.addLayer(that.DRAWMOVEPOLYGON); } }); that.map.on('dblclick', function(e) { that.map.getContainer().style.cursor = ''; var tempPoints = []; for (var i = 0; i < that.DRAWPOLYGONPOINTS.length; i++) { tempPoints.push(that.DRAWPOLYGONPOINTS[i]); } let as = that.DRAWPOLYGON.getLatLngs()[0] as.pop() let last = as[0] as.push(last) for(let i=0;i<as.length-1;i++){ let distance_cust = as[i].distanceTo(as[i+1]); let myIcon_cust = L.divIcon({ // html: (distance / 1000).toFixed(2) + "公里", className: 'my-div-icon', html:"<div>"+"<p>"+(distance_cust / 1000).toFixed(2)+"KM</p>"+"</div>", iconSize:26 }); let site_c = L.polyline([as[i],as[i+1]],{color:'rgba(0,0,0,0)',}).addTo(that.measureGroup); let as_ccc = site_c.getCenter() let c = new L.Marker(as_ccc, { draggable: false,icon: myIcon_cust}); that.measureGroup.addLayer(c) } console.log(as); tempPoints.push(e.latlng); let CC = that.DRAWPOLYGON.getCenter() var distance = CalArea(tempPoints); var myIcon = L.divIcon({ html:"<div>"+"<p>"+(distance / 1000000).toFixed(3)+"KM²</p>"+"</div>", className: 'my-div-icon', iconSize:26 }); let marker = new L.Marker(CC, { draggable: false,icon:myIcon }); that.measureGroup.addLayer(marker); // marker.bindPopup("总面积:" + (distance / 1000000).toFixed(3) + '平方公里').openPopup(); if (that.DRAWING) { if (that.DRAWMOVEPOLYGON != undefined && that.DRAWMOVEPOLYGON != null) { that.map.removeLayer(that.DRAWMOVEPOLYGON); that.DRAWMOVEPOLYGON = null; } that.BarDRAWLAYERS.push(that.DRAWPOLYGON); that.DRAWPOLYGONPOINTS = []; that.DRAWING = false; that.ISMEASURE = false; that.map.off('mousedown'); that.map.off('mousemove'); that.map.off('dblclick'); } }); var shapeOptions = { color: '#3388ff', weight: 3, opacity: 0.8, fill: true, fillColor: null, fillOpacity: 0.2, clickable: true } that.DRAWPOLYGON = new L.Polygon([], shapeOptions); that.measureGroup.addLayer(that.DRAWPOLYGON); if (that.ISMEASURE) { that.MEASUREAREATOOLTIP = new L.Tooltip(that.map); } function CalArea(latLngs) { var pointsCount = latLngs.length, area = 0.0, d2r = Math.PI / 180, p1, p2; if (pointsCount > 2) { for (var i = 0; i < pointsCount; i++) { p1 = latLngs[i]; p2 = latLngs[(i + 1) % pointsCount]; area += ((p2.lng - p1.lng) * d2r) * (2 + Math.sin(p1.lat * d2r) + Math.sin(p2.lat * d2r)); } area = area * 6378137.0 * 6378137.0 / 2.0; } return Math.abs(area); } }}export default DrawPlug

February 17, 2022 · 3 min · jiezi

关于leaflet:leaflet加载本地shapefile的zip包

业务场景:通过el-upload上传shapefile的zip文件,而后在地图上加载采纳了shp.js包 <div class="upload-file"> <el-upload class="upload-demo" drag :http-request="UploadShp" :before-upload="onBeforeUploadImage" action="string" multiple> <i class="el-icon-upload"></i> <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div> <div class="el-upload__tip" slot="tip">需.zip文件模式,至多包含.dbf、.shp、.prj三类文件</div> </el-upload></div>原作者:地址:https://segmentfault.com/u/yo...这个shp.js包巨坑,Readme说是间接传zip的url或者间接本地读取到的zip间接传入就能够,然而把他源码拆开看须要传arrayBuffer格局的,而且只能传这种格局。心愿这个包的作者看到这篇文章的时候去改一下报错提醒,或者改一下备注!!!!!太坑了 onBeforeUploadImage(file){ this.fileToBuf(file)},fileToBuf(file){ let that = this var fr = new FileReader(); fr.readAsArrayBuffer(file); fr.addEventListener("loadend",(e) => { var buf = e.target.result; shp(buf).then(function(data){ data.features.forEach(element => { var latlngs = element.geometry.coordinates let a = [] latlngs[0].forEach(element => { a.push([element[1],element[0]]) }); //supermap idesktop生成的shepefile的经纬度对于leaflet来说是反的,所以这里调整了一下 L.polygon(a, {color: 'red',fillColor:'rgba(255,0,0,0.1)'}).addTo(that.map); }); }); },false);},

December 27, 2021 · 1 min · jiezi

关于leaflet:支持Canvas的LeafletPathDashFlow动态流向线

通过对leaflet以及其插件的学习,咱们理解到应用Leaflet.Path.DashFlow插件可实现轨迹动静展现、管道流向动静展现、河流流向动静展现等,达到加强可视化展现的成果。该插件应用形式非常简单,只需在失常增加线的时候,退出dashArray和dashSpeed参数即可。外围代码如下: 留神,在dashSpeed为负时,线是正向流动。成果如下: 然而在应用的过程中,发现该插件有个弊病,就是当应用Canvas形式绘制地图(初始化地图preferCanvas参数为true)时,动态效果不可用。那要如何解决这个问题呢? 通过对Leaflet.Path.DashFlow以及leaflet源码的钻研,发现动静线的成果次要是通过动静刷新dashOffset参数的值,以扭转线的款式来实现。 L.SVG在_updateStyle的时候,更新了dashOffset参数,然而L.Canvas在_updateStyle时,并没有更新dashOffset参数。这即是在Canvas形式绘制时没有动态效果的起因。 L.SVG: L.Canvas: 由此,咱们找到了解决思路,即在L.Canvas的_updateStyle办法中,参考L.SVG的解决形式,增加对dashOffset参数的管制。外围代码如下: 为方便使用,咱们将L.Path.DashFlow插件从新封装,大家援用这个插件,即可在Canvas和SVG两种形式下应用此插件。 总结应用Leaflet.Path.DashFlow插件可实现轨迹动静展现、管道流向动静展现等动静线成果。默认插件在应用Canvas形式绘制地图(初始化地图preferCanvas参数为true)时,动态效果不可用。通过批改L.Canvas中代码,即可在Canvas形式时实现动静线成果。将L.Path.DashFlow插件从新封装,援用插件,即可在Canvas和SVG两种形式下实现动静线成果。在线示例[在线示例](http://gisarmory.xyz/blog/ind... [残缺代码](http://gisarmory.xyz/blog/ind... 原文地址:http://gisarmory.xyz/blog/index.html?blog=LeafletPathDashFlow。 关注《GIS兵器库》公众号, 第一工夫取得更多高质量GIS文章。 本文章采纳 常识共享署名-非商业性应用-雷同形式共享 4.0 国内许可协定 进行许可。欢送转载、应用、从新公布,但务必保留文章署名《GIS兵器库》(蕴含链接:  http://gisarmory.xyz/blog/),不得用于商业目标,基于本文批改后的作品务必以雷同的许可公布。

November 10, 2020 · 1 min · jiezi