@goshawk22/leaflet-elevation
Version:
A Leaflet plugin that allows to add elevation profiles using d3js
1 lines • 12.9 kB
JavaScript
L.Control.EdgeScale=L.Control.extend({options:{position:"bottomleft",icon:!0,coords:!0,bar:!0,onMove:!0,template:"{y} | {x}",projected:!1,formatProjected:"#.##0,000",latlngFormat:"DD",latlngDesignators:!0,latLngFormatter:void 0,iconStyle:{background:"url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xml:space='preserve' viewBox='0 0 100 100'%3E%3Cg stroke='%23fff'%3E%3Ccircle cx='50' cy='50.2' r='3.9' stroke-width='2' /%3E%3Cpath stroke-width='3' d='M5 54h32a4 4 0 1 0 0-8H5a4 4 0 1 0 0 8z M54 5a4 4 0 1 0-8 0v32a4 4 0 1 0 8 0V5z M99 50c0-2-2-4-4-4H63a4 4 0 1 0 0 8h32c2 0 4-1 4-4zM46 95a4 4 0 1 0 8 0V64a4 4 0 1 0-8 0v31z'/%3E%3C/g%3E%3C/svg%3E%0A\")",width:"24px",height:"24px",left:"calc(50% - 12px)",top:"calc(50% - 12px)",content:"",display:"block",position:"absolute",zIndex:999,pointerEvents:"none"},containerStyle:{backgroundColor:"rgba(255, 255, 255, 0.7)",boxShadow:"0 0 5px #bbb",borderRadius:"3px",padding:"3px 2px",color:"#333",font:"11px/1.5 Consolas, monaco, monospace",writingMode:"vertical-lr"}},initialize:function(options){L.setOptions(this,options)},onAdd:function(map){return this.options.bar&&(this._scaleBar=new L.Control.EdgeScale.Layer(!0===this.options.bar?{}:this.options.bar).addTo(map)),this.options.icon&&(this._icon=L.DomUtil.create("div","leaflet-crosshair"),Object.assign(this._icon.style,this.options.iconStyle),map.getContainer().insertBefore(this._icon,map.getContainer().firstChild)),this._container=L.DomUtil.create("div","leaflet-control-mapcentercoord"),Object.assign(this._container.style,this.options.containerStyle),this.options.coords||(this._container.style.display="none"),L.DomEvent.disableClickPropagation(this._container),this._container.innerHTML=this._getMapCenterCoord(),map.on("move",this._onMapMove,this),map.on("moveend",this._onMapMove,this),this._container},onRemove:function(map){this.options.bar&&this._scaleBar.remove(),this.options.icon&&map.getContainer().removeChild(this._icon),map.off("move",this._onMapMove,this),map.off("moveend",this._onMapMove,this)},_onMapMove:function(e){(this.options.onMove||"moveend"===e.type)&&(this._container.innerHTML=this._getMapCenterCoord())},_getMapCenterCoord:function(){const center=this._map.getCenter();return this.options.projected?this._getProjectedCoord(this._map.options.crs.project(center)):this._getLatLngCoord(center)},_getProjectedCoord:function(center){return L.Util.template(this.options.template,{x:this._format(this.options.formatProjected,center.x),y:this._format(this.options.formatProjected,center.y)})},_getLatLngCoord:function(latLng){const{latLngFormatter:latLngFormatter,latlngFormat:latlngFormat,latlngDesignators:designators}=this.options;if(void 0!==latLngFormatter)return latLngFormatter(latLng.lat,latLng.lng);let lat,lng,deg,min,center={lat:latLng.lat,lng:latLng.lng,lng_neg:latLng.lng<0,lat_neg:latLng.lat<0};return center.lng<0&&(center.lng=Math.abs(center.lng)),center.lng>180&&(center.lng=360-center.lng,center.lng_neg=!center.lng_neg),center.lat<0&&(center.lat=Math.abs(center.lat)),"DM"===latlngFormat?(deg=parseInt(center.lng),lng=deg+"º "+this._format("00.000",60*(center.lng-deg))+"'",deg=parseInt(center.lat),lat=deg+"º "+this._format("00.000",60*(center.lat-deg))+"'"):"DMS"===latlngFormat?(deg=parseInt(center.lng),min=60*(center.lng-deg),lng=deg+"º "+this._format("00",parseInt(min))+"' "+this._format("00.0",60*(min-parseInt(min)))+"''",deg=parseInt(center.lat),min=60*(center.lat-deg),lat=deg+"º "+this._format("00",parseInt(min))+"' "+this._format("00.0",60*(min-parseInt(min)))+"''"):(lng=this._format("#0.00000",center.lng)+"º",lat=this._format("##0.00000",center.lat)+"º"),L.Util.template(this.options.template,{x:(!designators&¢er.lng_neg?"-":"")+lng+(designators?center.lng_neg?" W":" E":""),y:(!designators&¢er.lat_neg?"-":"")+lat+(designators?center.lat_neg?" S":" N":"")})},_format:function(m,v){if(!m||isNaN(+v))return v;let isNegative=(v="-"==m.charAt(0)?-v:+v)<0?v=-v:0,result=m.match(/[^\d\-\+#]/g),Decimal=result&&result[result.length-1]||".",Group=result&&result[1]&&result[0]||",";m=m.split(Decimal),v=+(v=v.toFixed(m[1]&&m[1].length))+"";let pos_trail_zero=m[1]&&m[1].lastIndexOf("0"),part=v.split(".");(!part[1]||part[1]&&part[1].length<=pos_trail_zero)&&(v=(+v).toFixed(pos_trail_zero+1));let szSep=m[0].split(Group);m[0]=szSep.join("");let pos_lead_zero=m[0]&&m[0].indexOf("0");if(pos_lead_zero>-1)for(;part[0].length<m[0].length-pos_lead_zero;)part[0]="0"+part[0];else 0==+part[0]&&(part[0]="");(v=v.split("."))[0]=part[0];var pos_separator=szSep[1]&&szSep[szSep.length-1].length;if(pos_separator){let integer=v[0],str="",offset=integer.length%pos_separator;for(let i=0,l=integer.length;i<l;i++)str+=integer.charAt(i),!((i-offset+1)%pos_separator)&&i<l-pos_separator&&(str+=Group);v[0]=str}return v[1]=m[1]&&v[1]?Decimal+v[1]:"",(isNegative?"-":"")+v[0]+v[1]}}),L.Control.EdgeScale.Layer=L.Layer.extend({includes:L.Evented?L.Evented.prototype:L.Mixin.Events,options:{opacity:1,weight:.8,gradient:{size:10,opacity:.5},color:"#000",font:"11px Arial",zoomInterval:[{start:0,end:2,interval:5e6},{start:3,end:3,interval:2e6},{start:4,end:4,interval:1e6},{start:5,end:5,interval:5e5},{start:6,end:7,interval:2e5},{start:8,end:8,interval:1e5},{start:9,end:9,interval:5e4},{start:10,end:10,interval:2e4},{start:11,end:11,interval:1e4},{start:12,end:12,interval:5e3},{start:13,end:13,interval:2e3},{start:14,end:14,interval:1e3},{start:15,end:15,interval:500},{start:16,end:16,interval:200},{start:17,end:17,interval:100},{start:18,end:18,interval:50},{start:19,end:19,interval:20},{start:20,end:20,interval:10}],pane:"edgescalePane"},initialize:function(options){L.setOptions(this,options);const a=this._a=6378137,b=this._b=6356752.3142,n=this._n=(a-b)/(a+b),a2=a*a,b2=b*b,n2=n*n,n3=n2*n,n4=n3*n,n5=n4*n;this._A=a*(1-n)*(1-n2)*(1+9/4*n2+225/64*n4),this._e2=(a2-b2)/a2,this._ic1=1.5*n-29/12*n3+6.9125*n5,this._ic2=21/8*n2-1537/128*n4,this._ic3=151/24*n3-32373/640*n5,this._ic4=1097/64*n4,this._ic5=8011/150*n5,this._c1=-1.5*n+31/24*n3-669/640*n5,this._c2=15/18*n2-435/128*n4,this._c3=-35/12*n3+8.1375*n5,this._c4=315/64*n4,this._c5=-8.6625*n5,this._LIMIT_PHI=1.484419982},onAdd:function(map){this._map=map;let pane=map.getPane(this.options.pane);pane||(pane=this._pane=map.createPane("edgescalePane",map.getPane("norotatePane")||map.getPane("mapPane")),pane.style.zIndex=625,pane.style.pointerEvents="none"),this._pane=pane,this._canvas||this._initCanvas(),this._pane.appendChild(this._canvas),map.on("viewreset",this._reset,this),map.on("move",this._reset,this),map.on("moveend",this._reset,this),map.on("rotate",this._reset,this),this._reset()},onRemove:function(map){this._pane.removeChild(this._canvas),map.off("viewreset",this._reset,this),map.off("move",this._reset,this),map.off("moveend",this._reset,this)},addTo:function(map){return map.addLayer(this),this},setOpacity:function(opacity){return this.options.opacity=opacity,L.DomUtil.setOpacity(this._canvas,this.options.opacity),this},bringToFront:function(){return this._canvas&&this._pane.appendChild(this._canvas),this},bringToBack:function(){return this._canvas&&this._pane.insertBefore(this._canvas,pane.firstChild),this},_initCanvas:function(){this._canvas=L.DomUtil.create("canvas",""),this._ctx=this._canvas.getContext("2d"),this.setOpacity(),L.extend(this._canvas,{onselectstart:L.Util.falseFn,onmousemove:L.Util.falseFn,onload:L.bind(this._onCanvasLoad,this)})},_reset:function(){var canvas=this._canvas,size=this._map.getSize();if(this._setCanvasPosition(),canvas.width=size.x,canvas.height=size.y,canvas.style.width=size.x+"px",canvas.style.height=size.y+"px",this._map._bearing)return;const{gradient:gradient}=this.options;this._hor_gradient||(this._hor_gradient=this._ctx.createLinearGradient(0,0,0,gradient.size),this._hor_gradient.addColorStop(0,"rgba(255, 255, 255, "+gradient.opacity+")"),this._hor_gradient.addColorStop(1,"rgba(255, 255, 255, 0)")),this._ctx.fillStyle=this._hor_gradient,this._ctx.fillRect(0,0,size.x,gradient.size),this._vert_gradient||(this._vert_gradient=this._ctx.createLinearGradient(0,0,gradient.size,0),this._vert_gradient.addColorStop(0,"rgba(255, 255, 255, "+gradient.opacity+")"),this._vert_gradient.addColorStop(1,"rgba(255, 255, 255, 0)")),this._ctx.fillStyle=this._vert_gradient,this._ctx.fillRect(0,0,gradient.size,size.y),this._ctx.beginPath(),this._ctx.moveTo(0,0),this._ctx.lineTo(size.x,0),this._ctx.lineTo(size.x,size.y),this._ctx.stroke(),this._calcInterval(),this._draw()},_onCanvasLoad:function(){this.fire("load")},_calcInterval:function(){const{zoomInterval:zoomInterval}=this.options,zoom=this._map.getZoom();if(void 0!==zoomInterval)for(const idx in zoomInterval){const dict=zoomInterval[idx];if(dict.start<=zoom&&dict.end&&dict.end>=zoom){this._interval=dict.interval;break}}else this._interval=L.Control.Scale.prototype._getRoundNum(this._map.containerPointToLatLng([0,this._map.getSize().y/2]).distanceTo(this._map.containerPointToLatLng([L.Control.Scale.prototype.options.maxWidth,this._map.getSize().y/2])));this._currZoom=zoom},_draw:function(){this._ctx.strokeStyle=this.options.color,this._create_lat_ticks(),this._create_lon_ticks(),this._ctx.fillStyle=this.options.color,this._ctx.font=this.options.font;const size=this._map.getSize(),text=this._interval>=1e3?this._interval/1e3+" km":this._interval+" m";this._ctx.textAlign="left",this._ctx.textBaseline="middle",this._ctx.fillText(text,12,size.y/2),this._ctx.textAlign="center",this._ctx.textBaseline="top",this._ctx.fillText(text,size.x/2,12)},_create_lat_ticks:function(){const{weight:weight}=this.options,size=this._map.getSize(),to_rad=Math.PI/180,center=this._merLength(this._map.containerPointToLatLng(L.point(0,size.y/2)).lat*to_rad),top=this._merLength(this._map.containerPointToLatLng(L.point(0,0)).lat*to_rad),bottom=this._merLength(this._map.containerPointToLatLng(L.point(0,size.y)).lat*to_rad);for(let i=center+this._interval/2;i<top;i+=this._interval){const phi=this._invmerLength(i);phi<this._LIMIT_PHI&&phi>-this._LIMIT_PHI&&this._draw_lat_tick(phi,10,1.5*weight)}for(let i=center-this._interval/2;i>bottom;i-=this._interval){const phi=this._invmerLength(i);phi>-this._LIMIT_PHI&&phi<this._LIMIT_PHI&&this._draw_lat_tick(phi,10,1.5*weight)}for(let i=center;i<top;i+=this._interval/10){const phi=this._invmerLength(i);phi<this._LIMIT_PHI&&phi>-this._LIMIT_PHI&&this._draw_lat_tick(phi,4,weight)}for(let i=center-this._interval/10;i>bottom;i-=this._interval/10){const phi=this._invmerLength(i);phi>-this._LIMIT_PHI&&phi<this._LIMIT_PHI&&this._draw_lat_tick(phi,4,weight)}},_create_lon_ticks:function(){const{weight:weight}=this.options,size=this._map.getSize(),to_rad=Math.PI/180,to_deg=180/Math.PI,center=this._map.containerPointToLatLng(L.point(size.x/2,0)),left=this._map.containerPointToLatLng(L.point(0,0)),right=this._map.containerPointToLatLng(L.point(size.x,0)),sinPhi2=Math.pow(Math.sin(center.lat*to_rad),2),N=this._a/Math.sqrt(1-this._e2*sinPhi2),dl=this._interval/(N*Math.cos(center.lat*to_rad))*to_deg;for(let i=center.lng+dl/2;i<right.lng;i+=dl)this._draw_lon_tick(i,10,1.5*weight);for(let i=center.lng-dl/2;i>left.lng;i-=dl)this._draw_lon_tick(i,10,1.5*weight);for(let i=center.lng;i<right.lng;i+=dl/10)this._draw_lon_tick(i,4,weight);for(let i=center.lng-dl/10;i>left.lng;i-=dl/10)this._draw_lon_tick(i,4,weight)},_setCanvasPosition:function(){let lt=this._map.containerPointToLayerPoint([0,0]);this._map._bearing&&(lt=this._map.rotatedPointToMapPanePoint(this._map.containerPointToLayerPoint(L.point(this._map._container.getBoundingClientRect())))),L.DomUtil.setPosition(this._canvas,lt)},_latLngToCanvasPoint:function(latlng){return L.point(this._map.project(L.latLng(latlng))._subtract(this._map.getPixelOrigin())).add(this._map._getMapPanePos())},_draw_lat_tick:function(phi,lenght,weight){const to_deg=180/Math.PI,size=this._map.getSize(),y=this._latLngToCanvasPoint(L.latLng(phi*to_deg,0)).y;this._ctx.lineWidth=weight,this._ctx.beginPath(),this._ctx.moveTo(0,y),this._ctx.lineTo(+lenght,y),this._ctx.stroke()},_draw_lon_tick:function(lam,lenght,weight){const x=this._latLngToCanvasPoint(L.latLng(0,lam)).x;this._ctx.lineWidth=weight,this._ctx.beginPath(),this._ctx.moveTo(x,0),this._ctx.lineTo(x,lenght),this._ctx.stroke()},_merLength:function(phi){const cos2=Math.cos(2*phi),sin2=Math.sin(2*phi);return this._A*(phi+sin2*(this._c1+(this._c2+(this._c3+(this._c4+this._c5*cos2)*cos2)*cos2)*cos2))},_invmerLength:function(s){const psi=s/this._A,cos2=Math.cos(2*psi),sin2=Math.sin(2*psi);return psi+sin2*(this._ic1+(this._ic2+(this._ic3+(this._ic4+this._ic5*cos2)*cos2)*cos2)*cos2)}}),L.control.edgeScale=function(options){return new L.Control.EdgeScale(options)},L.Map.mergeOptions({edgeScaleControl:!1}),L.Map.addInitHook((function(){this.options.edgeScaleControl&&(this.edgeScaleControl=new L.Control.EdgeScale,this.addControl(this.edgeScaleControl))}));