node-red-contrib-web-worldmap 2.21.2 → 2.21.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/README.md +4 -6
- package/package.json +1 -1
- package/worldmap/css/worldmap.css +1 -1
- package/worldmap/index.html +1 -0
- package/worldmap/leaflet/L.TileLayer.PixelFilter.js +152 -0
- package/worldmap/leaflet/leaflet-velocity.min.js +1 -1
- package/worldmap/worldmap.js +54 -18
- package/worldmap/worldmaphead.html +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
### Change Log for Node-RED Worldmap
|
|
2
2
|
|
|
3
|
+
- v2.21.5 - Fix handling of "old" ship nav to ship navigation
|
|
4
|
+
- v2.21.4 - Fix speed leader length. Add transparentPixels option.
|
|
5
|
+
- v2.21.3 - Add zoom to bounds action. Adjust map layers max zoom levels.
|
|
6
|
+
- v2.21.2 - Expand ship nav to ship navigation.
|
|
3
7
|
- v2.21.1 - Fix ui check callback to not use .
|
|
4
8
|
- v2.21.0 - Let config panel select maps to show, default map and choice of overlays.
|
|
5
9
|
- v2.20.0 - Add support of .pbf map layers. Issue #123.
|
package/README.md
CHANGED
|
@@ -11,6 +11,10 @@ map web page for plotting "things" on.
|
|
|
11
11
|
|
|
12
12
|
### Updates
|
|
13
13
|
|
|
14
|
+
- v2.21.5 - Fix handling of "old" ship nav to ship navigation
|
|
15
|
+
- v2.21.4 - Fix speed leader length. Add transparentPixels option..
|
|
16
|
+
- v2.21.3 - Add zoom to bounds action. Adjust map layers max zoom levels.
|
|
17
|
+
- v2.21.2 - Expand ship nav to ship navigation.
|
|
14
18
|
- v2.21.1 - Fix ui check callback to not use .
|
|
15
19
|
- v2.21.0 - Let config panel select maps to show, default map and choice of overlays.
|
|
16
20
|
- v2.20.0 - Add support of .pbf map layers. Issue 123.
|
|
@@ -31,12 +35,6 @@ map web page for plotting "things" on.
|
|
|
31
35
|
- v2.15.3 - Fix panit command to work, try to use alt units, popup alignments.
|
|
32
36
|
- v2.15.0 - Let speed be text and specify units if required (kt,kn,knots,mph,kmh,kph) default m/s.
|
|
33
37
|
- v2.14.0 - Let geojson features be clickable if added as overlay.
|
|
34
|
-
- v2.13.4 - Fix list of map choices to be in sync. Fix popup auto sizing.
|
|
35
|
-
- v2.13.3 - Fix unchanged layer propagation.
|
|
36
|
-
- v2.13.2 - Add mayflower icon.
|
|
37
|
-
- v2.13.0 - Tidy velocity layer. Feedback any url parameters.
|
|
38
|
-
- v2.12.1 - Only show online layer options if we are online.
|
|
39
|
-
- v2.12.0 - Add live rainfall radar data layer. Remove some non-loading overlays.
|
|
40
38
|
|
|
41
39
|
- see [CHANGELOG](https://github.com/dceejay/RedMap/blob/master/CHANGELOG.md) for full list of changes.
|
|
42
40
|
|
package/package.json
CHANGED
package/worldmap/index.html
CHANGED
|
@@ -72,6 +72,7 @@
|
|
|
72
72
|
<script src="leaflet/leaflet.latlng-graticule.js"></script>
|
|
73
73
|
<script src="leaflet/VectorTileLayer.umd.min.js"></script>
|
|
74
74
|
<script src="leaflet/Semicircle.js"></script>
|
|
75
|
+
<script src="leaflet/L.TileLayer.PixelFilter.js"></script>
|
|
75
76
|
<script src="leaflet/dialog-polyfill.js"></script>
|
|
76
77
|
|
|
77
78
|
<script src="images/emoji.js"></script>
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* L.TileLayer.PixelFilter
|
|
3
|
+
* https://github.com/greeninfo/L.TileLayer.PixelFilter
|
|
4
|
+
* http://greeninfo-network.github.io/L.TileLayer.PixelFilter/
|
|
5
|
+
*/
|
|
6
|
+
L.tileLayerPixelFilter = function (url, options) {
|
|
7
|
+
return new L.TileLayer.PixelFilter(url, options);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
L.TileLayer.PixelFilter = L.TileLayer.extend({
|
|
11
|
+
// the constructor saves settings and throws a fit if settings are bad, as typical
|
|
12
|
+
// then adds the all-important 'tileload' event handler which basically "detects" an unmodified tile and performs the pxiel-swap
|
|
13
|
+
initialize: function (url, options) {
|
|
14
|
+
options = L.extend({}, L.TileLayer.prototype.options, {
|
|
15
|
+
matchRGBA: null,
|
|
16
|
+
missRGBA: null,
|
|
17
|
+
pixelCodes: [],
|
|
18
|
+
crossOrigin: 'Anonymous', // per issue 15, this is how you do it in Leaflet 1.x
|
|
19
|
+
}, options);
|
|
20
|
+
L.TileLayer.prototype.initialize.call(this, url, options);
|
|
21
|
+
L.setOptions(this, options);
|
|
22
|
+
|
|
23
|
+
// go ahead and save our settings
|
|
24
|
+
this.setMatchRGBA(this.options.matchRGBA);
|
|
25
|
+
this.setMissRGBA(this.options.missRGBA);
|
|
26
|
+
this.setPixelCodes(this.options.pixelCodes);
|
|
27
|
+
|
|
28
|
+
// and add our tile-load event hook which triggers us to do the pixel-swap
|
|
29
|
+
this.on('tileload', function (event) {
|
|
30
|
+
this.applyFiltersToTile(event.tile);
|
|
31
|
+
});
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
// settings setters
|
|
35
|
+
setMatchRGBA: function (rgba) {
|
|
36
|
+
// save the setting
|
|
37
|
+
if (rgba !== null && (typeof rgba !== 'object' || typeof rgba.length !== 'number' || rgba.length !== 4) ) throw "L.TileLayer.PixelSwap expected matchRGBA to be RGBA [r,g,b,a] array or else null";
|
|
38
|
+
this.options.matchRGBA = rgba;
|
|
39
|
+
|
|
40
|
+
// force a redraw, which means new tiles, which mean new tileload events; the circle of life
|
|
41
|
+
this.redraw(true);
|
|
42
|
+
},
|
|
43
|
+
setMissRGBA: function (rgba) {
|
|
44
|
+
// save the setting
|
|
45
|
+
if (rgba !== null && (typeof rgba !== 'object' || typeof rgba.length !== 'number' || rgba.length !== 4) ) throw "L.TileLayer.PixelSwap expected missRGBA to be RGBA [r,g,b,a] array or else null";
|
|
46
|
+
this.options.missRGBA = rgba;
|
|
47
|
+
|
|
48
|
+
// force a redraw, which means new tiles, which mean new tileload events; the circle of life
|
|
49
|
+
this.redraw(true);
|
|
50
|
+
},
|
|
51
|
+
setPixelCodes: function (pixelcodes) {
|
|
52
|
+
// save the setting
|
|
53
|
+
if (typeof pixelcodes !== 'object' || typeof pixelcodes.length !== 'number') throw "L.TileLayer.PixelSwap expected pixelCodes to be a list of triplets: [ [r,g,b], [r,g,b], ... ]";
|
|
54
|
+
this.options.pixelCodes = pixelcodes;
|
|
55
|
+
|
|
56
|
+
// force a redraw, which means new tiles, which mean new tileload events; the circle of life
|
|
57
|
+
this.redraw(true);
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
// extend the _createTile function to add the .crossOrigin attribute, since loading tiles from a separate service is a pretty common need
|
|
61
|
+
// and the Canvas is paranoid about cross-domain image data. see issue #5
|
|
62
|
+
// this is really only for Leaflet 0.7; as of 1.0 L.TileLayer has a crossOrigin setting which we define as a layer option
|
|
63
|
+
_createTile: function () {
|
|
64
|
+
var tile = L.TileLayer.prototype._createTile.call(this);
|
|
65
|
+
tile.crossOrigin = "Anonymous";
|
|
66
|
+
return tile;
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
// the heavy lifting to do the pixel-swapping
|
|
70
|
+
// called upon 'tileload' and passed the IMG element
|
|
71
|
+
// tip: when the tile is saved back to the IMG element that counts as a tileload event too! thus an infinite loop, as wel as comparing the pixelCodes against already-replaced pixels!
|
|
72
|
+
// so, we tag the already-swapped tiles so we know when to quit
|
|
73
|
+
// if the layer is redrawn, it's a new IMG element and that means it would not yet be tagged
|
|
74
|
+
applyFiltersToTile: function (imgelement) {
|
|
75
|
+
// already processed, see note above
|
|
76
|
+
if (imgelement.getAttribute('data-PixelFilterDone')) return;
|
|
77
|
+
|
|
78
|
+
// copy the image data onto a canvas for manipulation
|
|
79
|
+
var width = imgelement.width;
|
|
80
|
+
var height = imgelement.height;
|
|
81
|
+
var canvas = document.createElement("canvas");
|
|
82
|
+
canvas.width = width;
|
|
83
|
+
canvas.height = height;
|
|
84
|
+
var context = canvas.getContext("2d");
|
|
85
|
+
context.drawImage(imgelement, 0, 0);
|
|
86
|
+
|
|
87
|
+
// create our target imagedata
|
|
88
|
+
var output = context.createImageData(width, height);
|
|
89
|
+
|
|
90
|
+
// extract out our RGBA trios into separate numbers, so we don't have to use rgba[i] a zillion times
|
|
91
|
+
var matchRGBA = this.options.matchRGBA, missRGBA = this.options.missRGBA;
|
|
92
|
+
if (matchRGBA !== null) {
|
|
93
|
+
var match_r = matchRGBA[0], match_g = matchRGBA[1], match_b = matchRGBA[2], match_a = matchRGBA[3];
|
|
94
|
+
}
|
|
95
|
+
if (missRGBA !== null) {
|
|
96
|
+
var miss_r = missRGBA[0], miss_g = missRGBA[1], miss_b = missRGBA[2], miss_a = missRGBA[3];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// go over our pixel-code list and generate the list of integers that we'll use for RGB matching
|
|
100
|
+
// 1000000*R + 1000*G + B = 123123123 which is an integer, and finding an integer inside an array is a lot faster than finding an array inside an array
|
|
101
|
+
var pixelcodes = [];
|
|
102
|
+
for (var i=0, l=this.options.pixelCodes.length; i<l; i++) {
|
|
103
|
+
var value = 1000000 * this.options.pixelCodes[i][0] + 1000 * this.options.pixelCodes[i][1] + this.options.pixelCodes[i][2];
|
|
104
|
+
pixelcodes.push(value);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// iterate over the pixels (each one is 4 bytes, RGBA)
|
|
108
|
+
// and see if they are on our list (recall the "addition" thing so we're comparing integers in an array for performance)
|
|
109
|
+
// per issue #5 catch a failure here, which is likely a cross-domain problem
|
|
110
|
+
try {
|
|
111
|
+
var pixels = context.getImageData(0, 0, width, height).data;
|
|
112
|
+
} catch(e) {
|
|
113
|
+
throw "L.TileLayer.PixelFilter getImageData() failed. Likely a cross-domain issue?";
|
|
114
|
+
}
|
|
115
|
+
for(var i = 0, n = pixels.length; i < n; i += 4) {
|
|
116
|
+
var r = pixels[i ];
|
|
117
|
+
var g = pixels[i+1];
|
|
118
|
+
var b = pixels[i+2];
|
|
119
|
+
var a = pixels[i+3];
|
|
120
|
+
|
|
121
|
+
// bail condition: if the alpha is 0 then it's already transparent, likely nodata, and we should skip it
|
|
122
|
+
if (a == 0) {
|
|
123
|
+
output.data[i ] = 255;
|
|
124
|
+
output.data[i+1] = 255;
|
|
125
|
+
output.data[i+2] = 255;
|
|
126
|
+
output.data[i+3] = 0;
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// default to matching, so that if we are not in fact filtering by code it's an automatic hit
|
|
131
|
+
// number matching trick: 1000000*R + 1000*G + 1*B = 123,123,123 a simple number that either is or isn't on the list
|
|
132
|
+
var match = true;
|
|
133
|
+
if (pixelcodes.length) {
|
|
134
|
+
var sum = 1000000 * r + 1000 * g + b;
|
|
135
|
+
if (-1 === pixelcodes.indexOf(sum)) match = false;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// did it match? either way we push a R, a G, and a B onto the image blob
|
|
139
|
+
// if the target RGBA is a null, then we push exactly the same RGBA as we found in the source pixel
|
|
140
|
+
output.data[i ] = match ? (matchRGBA===null ? r : match_r) : (missRGBA===null ? r : miss_r);
|
|
141
|
+
output.data[i+1] = match ? (matchRGBA===null ? g : match_g) : (missRGBA===null ? g : miss_g);
|
|
142
|
+
output.data[i+2] = match ? (matchRGBA===null ? b : match_b) : (missRGBA===null ? b : miss_b);
|
|
143
|
+
output.data[i+3] = match ? (matchRGBA===null ? a : match_a) : (missRGBA===null ? a : miss_a);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// write the image back to the canvas, and assign its base64 back into the on-screen tile to visualize the change
|
|
147
|
+
// tag the tile as having already been updated, so we don't process a 'load' event again and re-process a tile that surely won't match any target RGB codes, in an infinite loop!
|
|
148
|
+
context.putImageData(output, 0, 0);
|
|
149
|
+
imgelement.setAttribute('data-PixelFilterDone', true);
|
|
150
|
+
imgelement.src = canvas.toDataURL();
|
|
151
|
+
}
|
|
152
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";L.DomUtil.setTransform||(L.DomUtil.setTransform=function(t,n,e){var i=n||new L.Point(0,0);t.style[L.DomUtil.TRANSFORM]=(L.Browser.ie3d?"translate("+i.x+"px,"+i.y+"px)":"translate3d("+i.x+"px,"+i.y+"px,0)")+(e?" scale("+e+")":"")}),L.CanvasLayer=(L.Layer?L.Layer:L.Class).extend({initialize:function(t){this._map=null,this._canvas=null,this._frame=null,this._delegate=null,L.setOptions(this,t)},delegate:function(t){return this._delegate=t,this},needRedraw:function(){return this._frame||(this._frame=L.Util.requestAnimFrame(this.drawLayer,this)),this},_onLayerDidResize:function(t){this._canvas.width=t.newSize.x,this._canvas.height=t.newSize.y},_onLayerDidMove:function(){var t=this._map.containerPointToLayerPoint([0,0]);L.DomUtil.setPosition(this._canvas,t),this.drawLayer()},getEvents:function(){var t={resize:this._onLayerDidResize,moveend:this._onLayerDidMove};return this._map.options.zoomAnimation&&L.Browser.any3d&&(t.zoomanim=this._animateZoom),t},onAdd:function(t){this._map=t,this._canvas=L.DomUtil.create("canvas","leaflet-layer"),this.tiles={};var n=this._map.getSize();this._canvas.width=n.x,this._canvas.height=n.y;var e=this._map.options.zoomAnimation&&L.Browser.any3d;L.DomUtil.addClass(this._canvas,"leaflet-zoom-"+(e?"animated":"hide")),this.options.pane.appendChild(this._canvas),t.on(this.getEvents(),this);var i=this._delegate||this;i.onLayerDidMount&&i.onLayerDidMount(),this.needRedraw();var o=this;setTimeout(function(){o._onLayerDidMove()},0)},onRemove:function(t){var n=this._delegate||this;n.onLayerWillUnmount&&n.onLayerWillUnmount(),this.options.pane.removeChild(this._canvas),t.off(this.getEvents(),this),this._canvas=null},addTo:function(t){return t.addLayer(this),this},drawLayer:function(){var t=this._map.getSize(),n=this._map.getBounds(),e=this._map.getZoom(),i=this._map.options.crs.project(this._map.getCenter()),o=this._map.options.crs.project(this._map.containerPointToLatLng(this._map.getSize())),a=this._delegate||this;a.onDrawLayer&&a.onDrawLayer({layer:this,canvas:this._canvas,bounds:n,size:t,zoom:e,center:i,corner:o}),this._frame=null},_setTransform:function(t,n,e){var i=n||new L.Point(0,0);t.style[L.DomUtil.TRANSFORM]=(L.Browser.ie3d?"translate("+i.x+"px,"+i.y+"px)":"translate3d("+i.x+"px,"+i.y+"px,0)")+(e?" scale("+e+")":"")},_animateZoom:function(t){var n=this._map.getZoomScale(t.zoom),e=L.Layer?this._map._latLngToNewLayerPoint(this._map.getBounds().getNorthWest(),t.zoom,t.center):this._map._getCenterOffset(t.center)._multiplyBy(-n).subtract(this._map._getMapPanePos());L.DomUtil.setTransform(this._canvas,e,n)}}),L.canvasLayer=function(t){return new L.CanvasLayer(t)},L.Control.Velocity=L.Control.extend({options:{position:"bottomleft",emptyString:"Unavailable",angleConvention:"bearingCCW",showCardinal:!1,speedUnit:"m/s",directionString:"Direction",speedString:"Speed",onAdd:null,onRemove:null},onAdd:function(t){return this._container=L.DomUtil.create("div","leaflet-control-velocity"),L.DomEvent.disableClickPropagation(this._container),t.on("mousemove",this._onMouseMove,this),this._container.innerHTML=this.options.emptyString,this.options.leafletVelocity.options.onAdd&&this.options.leafletVelocity.options.onAdd(),this._container},onRemove:function(t){t.off("mousemove",this._onMouseMove,this),this.options.leafletVelocity.options.onRemove&&this.options.leafletVelocity.options.onRemove()},vectorToSpeed:function(t,n,e){var i=Math.sqrt(Math.pow(t,2)+Math.pow(n,2));return"k/h"===e?this.meterSec2kilometerHour(i):"kt"===e?this.meterSec2Knots(i):i},vectorToDegrees:function(t,n,e){e.endsWith("CCW")&&(n=0<n?n=-n:Math.abs(n));var i=Math.sqrt(Math.pow(t,2)+Math.pow(n,2)),o=180*Math.atan2(t/i,n/i)/Math.PI+180;return"bearingCW"!==e&&"meteoCCW"!==e||360<=(o+=180)&&(o-=360),o},degreesToCardinalDirection:function(t){var n="";return 0<=t&&t<11.25||348.75<=t?n="N":11.25<=t&&t<33.75?n="NNW":33.75<=t&&t<56.25?n="NW":56.25<=t&&t<78.75?n="WNW":78.25<=t&&t<101.25?n="W":101.25<=t&&t<123.75?n="WSW":123.75<=t&&t<146.25?n="SW":146.25<=t&&t<168.75?n="SSW":168.75<=t&&t<191.25?n="S":191.25<=t&&t<213.75?n="SSE":213.75<=t&&t<236.25?n="SE":236.25<=t&&t<258.75?n="ESE":258.75<=t&&t<281.25?n="E":281.25<=t&&t<303.75?n="ENE":303.75<=t&&t<326.25?n="NE":326.25<=t&&t<348.75&&(n="NNE"),n},meterSec2Knots:function(t){return t/.514},meterSec2kilometerHour:function(t){return 3.6*t},_onMouseMove:function(t){var n=this.options.leafletVelocity._map.containerPointToLatLng(L.point(t.containerPoint.x,t.containerPoint.y)),e=this.options.leafletVelocity._windy.interpolatePoint(n.lng,n.lat),i="";if(e&&!isNaN(e[0])&&!isNaN(e[1])&&e[2]){var o=this.vectorToDegrees(e[0],e[1],this.options.angleConvention),a=this.options.showCardinal?" (".concat(this.degreesToCardinalDirection(o),")"):"";i="<strong> ".concat(this.options.velocityType," ").concat(this.options.directionString,": </strong> ").concat(o.toFixed(2),"°").concat(a,", <strong> ").concat(this.options.speedString,": </strong> ").concat(this.vectorToSpeed(e[0],e[1],this.options.speedUnit).toFixed(2)," ").concat(this.options.speedUnit)}else i=this.options.emptyString;this._container.innerHTML=i}}),L.Map.mergeOptions({positionControl:!1}),L.Map.addInitHook(function(){this.options.positionControl&&(this.positionControl=new L.Control.MousePosition,this.addControl(this.positionControl))}),L.control.velocity=function(t){return new L.Control.Velocity(t)},L.VelocityLayer=(L.Layer?L.Layer:L.Class).extend({options:{displayValues:!0,displayOptions:{velocityType:"Velocity",position:"bottomleft",emptyString:"No velocity data"},maxVelocity:10,colorScale:null,data:null},_map:null,_canvasLayer:null,_windy:null,_context:null,_timer:0,_mouseControl:null,initialize:function(t){L.setOptions(this,t)},onAdd:function(t){this._paneName=this.options.paneName||"overlayPane";var n=t._panes.overlayPane;t.getPane&&(n=(n=t.getPane(this._paneName))||t.createPane(this._paneName)),this._canvasLayer=L.canvasLayer({pane:n}).delegate(this),this._canvasLayer.addTo(t),this._map=t},onRemove:function(t){this._destroyWind()},setData:function(t){this.options.data=t,this._windy&&(this._windy.setData(t),this._clearAndRestart()),this.fire("load")},setOpacity:function(t){console.log("this._canvasLayer",this._canvasLayer),this._canvasLayer.setOpacity(t)},setOptions:function(t){this.options=Object.assign(this.options,t),t.hasOwnProperty("displayOptions")&&(this.options.displayOptions=Object.assign(this.options.displayOptions,t.displayOptions),this._initMouseHandler(!0)),t.hasOwnProperty("data")&&(this.options.data=t.data),this._windy&&(this._windy.setOptions(t),t.hasOwnProperty("data")&&this._windy.setData(t.data),this._clearAndRestart()),this.fire("load")},onDrawLayer:function(t,n){var e=this;this._windy?this.options.data&&(this._timer&&clearTimeout(e._timer),this._timer=setTimeout(function(){e._startWindy()},750)):this._initWindy(this)},_startWindy:function(){var t=this._map.getBounds(),n=this._map.getSize();this._windy.start([[0,0],[n.x,n.y]],n.x,n.y,[[t._southWest.lng,t._southWest.lat],[t._northEast.lng,t._northEast.lat]])},_initWindy:function(t){var n=Object.assign({canvas:t._canvasLayer._canvas,map:this._map},t.options);this._windy=new Windy(n),this._context=this._canvasLayer._canvas.getContext("2d"),this._canvasLayer._canvas.classList.add("velocity-overlay"),this.onDrawLayer(),this._map.on("dragstart",t._windy.stop),this._map.on("dragend",t._clearAndRestart),this._map.on("zoomstart",t._windy.stop),this._map.on("zoomend",t._clearAndRestart),this._map.on("resize",t._clearWind),this._initMouseHandler(!1)},_initMouseHandler:function(t){if(t&&(this._map.removeControl(this._mouseControl),this._mouseControl=!1),!this._mouseControl&&this.options.displayValues){var n=this.options.displayOptions||{};(n.leafletVelocity=this)._mouseControl=L.control.velocity(n).addTo(this._map)}},_clearAndRestart:function(){this._context&&this._context.clearRect(0,0,3e3,3e3),this._windy&&this._startWindy()},_clearWind:function(){this._windy&&this._windy.stop(),this._context&&this._context.clearRect(0,0,3e3,3e3)},_destroyWind:function(){this._timer&&clearTimeout(this._timer),this._windy&&this._windy.stop(),this._context&&this._context.clearRect(0,0,3e3,3e3),this._mouseControl&&this._map.removeControl(this._mouseControl),this._mouseControl=null,this._windy=null,this._map.removeLayer(this._canvasLayer)}}),L.velocityLayer=function(t){return new L.VelocityLayer(t)};var Windy=function(b){function o(t,n,e,i,o,a){var r=1-t,s=1-n,l=r*s,h=t*s,c=r*n,d=t*n,p=e[0]*l+i[0]*h+o[0]*c+a[0]*d,u=e[1]*l+i[1]*h+o[1]*c+a[1]*d;return[p,u,Math.sqrt(p*p+u*u)]}function d(t){var n=null,e=null;return t.forEach(function(t){switch(t.header.parameterCategory+","+t.header.parameterNumber){case"1,2":case"2,2":n=t;break;case"1,3":case"2,3":e=t;break;default:t}}),function(t,n){var e=t.data,i=n.data;return{header:t.header,data:function(t){return[e[t],i[t]]},interpolate:o}}(n,e)}function a(i,o,t){function a(t,n){var e=i[Math.round(t)];return e&&e[Math.round(n)]||h}a.release=function(){i=[]},a.randomize=function(t){for(var n,e,i=0;null===a(n=Math.round(Math.floor(Math.random()*o.width)+o.x),e=Math.round(Math.floor(Math.random()*o.height)+o.y))[2]&&i++<30;);return t.x=n,t.y=e,t},t(o,a)}function r(t){return t/180*Math.PI}function s(i,s){var n,e,l=(n=x,e=C,R.indexFor=function(t){return Math.max(0,Math.min(R.length-1,Math.round((t-n)/(e-n)*(R.length-1))))},R),h=l.map(function(){return[]}),t=Math.round(i.width*i.height*D);/android|blackberry|iemobile|ipad|iphone|ipod|opera mini|webos/i.test(navigator.userAgent)&&(t*=T);for(var o="rgba(0, 0, 0, ".concat(O,")"),a=[],r=0;r<t;r++)a.push(s.randomize({age:Math.floor(Math.random()*P)+0}));var c=b.canvas.getContext("2d");c.lineWidth=S,c.fillStyle=o,c.globalAlpha=.6;var d=Date.now();!function t(){M=requestAnimationFrame(t);var n=Date.now(),e=n-d;W<e&&(d=n-e%W,h.forEach(function(t){t.length=0}),a.forEach(function(t){t.age>P&&(s.randomize(t).age=0);var n=t.x,e=t.y,i=s(n,e),o=i[2];if(null===o)t.age=P;else{var a=n+i[0],r=e+i[1];null!==s(a,r)[2]?(t.xt=a,t.yt=r,h[l.indexFor(o)].push(t)):(t.x=a,t.y=r)}t.age+=1}),c.globalCompositeOperation="destination-in",c.fillRect(i.x,i.y,i.width,i.height),c.globalCompositeOperation="lighter",c.globalAlpha=0===O?0:.9*O,h.forEach(function(t,n){0<t.length&&(c.beginPath(),c.strokeStyle=l[n],t.forEach(function(t){c.moveTo(t.x,t.y),c.lineTo(t.xt,t.yt),t.x=t.xt,t.y=t.yt}),c.stroke())}))}()}var u,m,p,y,_,f,v,g,w,M,x=b.minVelocity||0,C=b.maxVelocity||10,l=(b.velocityScale||.005)*(Math.pow(window.devicePixelRatio,1/3)||1),P=b.particleAge||90,S=b.lineWidth||1,D=b.particleMultiplier||1/300,T=Math.pow(window.devicePixelRatio,1/3)||1.6,n=b.frameRate||15,W=1e3/n,O=.97,R=b.colorScale||["rgb(36,104, 180)","rgb(60,157, 194)","rgb(128,205,193 )","rgb(151,218,168 )","rgb(198,231,181)","rgb(238,247,217)","rgb(255,238,159)","rgb(252,217,125)","rgb(255,182,100)","rgb(252,150,75)","rgb(250,112,52)","rgb(245,64,32)","rgb(237,45,28)","rgb(220,24,32)","rgb(180,0,35)"],h=[NaN,NaN,null],c=b.data,N=function(t,n){if(!m)return null;var e,i=z(t-y,360)/f,o=(_-n)/v,a=Math.floor(i),r=a+1,s=Math.floor(o),l=s+1;if(e=m[s]){var h=e[a],c=e[r];if(A(h)&&A(c)&&(e=m[l])){var d=e[a],p=e[r];if(A(d)&&A(p))return u.interpolate(i-a,o-s,h,c,d,p)}}return null},A=function(t){return null!=t},z=function(t,n){return t-n*Math.floor(t/n)},E=function(t,n,e,i,o){var a=2*Math.PI,r=n<0?5:-5,s=e<0?5:-5,l=V(e,n+r),h=V(e+s,n),c=Math.cos(e/360*a);return[(l[0]-i)/r/c,(l[1]-o)/r/c,(h[0]-i)/s,(h[1]-o)/s]},V=function(t,n,e){var i=b.map.latLngToContainerPoint(L.latLng(t,n));return[i.x,i.y]},U=function(){F.field&&F.field.release(),M&&cancelAnimationFrame(M)},F={params:b,start:function(n,e,i,t){var o={south:r(t[0][1]),north:r(t[1][1]),east:r(t[1][0]),west:r(t[0][0]),width:e,height:i};U(),function(t,n){var e=!0;t.length<2&&(e=!1),e||console.log("Windy Error: data must have at least two components (u,v)");var i=(u=d(t)).header;if(i.hasOwnProperty("gridDefinitionTemplate")&&0!=i.gridDefinitionTemplate&&(e=!1),e||console.log("Windy Error: Only data with Latitude_Longitude coordinates is supported"),e=!0,y=i.lo1,_=i.la1,f=i.dx,v=i.dy,g=i.nx,w=i.ny,i.hasOwnProperty("scanMode")){var o=i.scanMode.toString(2),a=(o=("0"+o).slice(-8)).split("").map(Number).map(Boolean);a[0]&&(f=-f),a[1]&&(v=-v),a[2]&&(e=!1),a[3]&&(e=!1),a[4]&&(e=!1),a[5]&&(e=!1),a[6]&&(e=!1),a[7]&&(e=!1),e||console.log("Windy Error: Data with scanMode: "+i.scanMode+" is not supported.")}(p=new Date(i.refTime)).setHours(p.getHours()+i.forecastTime),m=[];for(var r=0,s=360<=Math.floor(g*f),l=0;l<w;l++){for(var h=[],c=0;c<g;c++,r++)h[c]=u.data(r);s&&h.push(h[0]),m[l]=h}n({date:p,interpolate:N})}(c,function(t){!function(w,M,t,e){var x={},n=(t.south-t.north)*(t.west-t.east),C=l*Math.pow(n,.4),P=[],i=M.x;function o(t){for(var n,e,i,o,a,r,s,l,h,c,d,p,u,m=[],y=M.y;y<=M.yMax;y+=2){var _=(d=t,p=y,void 0,[(u=b.map.containerPointToLatLng(L.point(d,p))).lng,u.lat]),f=_[0],v=_[1];if(isFinite(f)){var g=w.interpolate(f,v);g&&(n=x,e=f,i=v,o=t,a=y,r=C,void 0,l=(s=g)[0]*r,h=s[1]*r,c=E(n,e,i,o,a),s[0]=c[0]*l+c[2]*h,s[1]=c[1]*l+c[3]*h,g=s,m[y+1]=m[y]=g)}}P[t+1]=P[t]=m}!function t(){for(var n=Date.now();i<M.width;)if(o(i),i+=2,1e3<Date.now()-n)return void setTimeout(t,25);a(P,M,e)}()}(t,function(t,n,e){var i=t[0],o=t[1],a=Math.round(i[0]),r=Math.max(Math.floor(i[1],0),0);Math.min(Math.ceil(o[0],n),n-1);return{x:a,y:r,xMax:n,yMax:Math.min(Math.ceil(o[1],e),e-1),width:n,height:e}}(n,e,i),o,function(t,n){F.field=n,s(t,n)})})},stop:U,createField:a,interpolatePoint:N,setData:function(t){c=t},setOptions:function(t){t.hasOwnProperty("minVelocity")&&(x=t.minVelocity),t.hasOwnProperty("maxVelocity")&&(C=t.maxVelocity),t.hasOwnProperty("velocityScale")&&(l=(t.velocityScale||.005)*(Math.pow(window.devicePixelRatio,1/3)||1)),t.hasOwnProperty("particleAge")&&(P=t.particleAge),t.hasOwnProperty("lineWidth")&&(S=t.lineWidth),t.hasOwnProperty("particleMultiplier")&&(D=t.particleMultiplier),t.hasOwnProperty("opacity")&&(O=+t.opacity),t.hasOwnProperty("frameRate")&&(n=t.frameRate),W=1e3/n}};return F};window.cancelAnimationFrame||(window.cancelAnimationFrame=function(t){clearTimeout(t)});
|
|
1
|
+
"use strict";L.DomUtil.setTransform||(L.DomUtil.setTransform=function(t,e,n){var i=e||new L.Point(0,0);t.style[L.DomUtil.TRANSFORM]=(L.Browser.ie3d?"translate("+i.x+"px,"+i.y+"px)":"translate3d("+i.x+"px,"+i.y+"px,0)")+(n?" scale("+n+")":"")}),L.CanvasLayer=(L.Layer?L.Layer:L.Class).extend({initialize:function(t){this._map=null,this._canvas=null,this._frame=null,this._delegate=null,L.setOptions(this,t)},delegate:function(t){return this._delegate=t,this},needRedraw:function(){return this._frame||(this._frame=L.Util.requestAnimFrame(this.drawLayer,this)),this},_onLayerDidResize:function(t){this._canvas.width=t.newSize.x,this._canvas.height=t.newSize.y},_onLayerDidMove:function(){var t=this._map.containerPointToLayerPoint([0,0]);L.DomUtil.setPosition(this._canvas,t),this.drawLayer()},getEvents:function(){var t={resize:this._onLayerDidResize,moveend:this._onLayerDidMove};return this._map.options.zoomAnimation&&L.Browser.any3d&&(t.zoomanim=this._animateZoom),t},onAdd:function(t){console.log("canvas onAdd",this),this._map=t,this._canvas=L.DomUtil.create("canvas","leaflet-layer"),this.tiles={};var e=this._map.getSize();this._canvas.width=e.x,this._canvas.height=e.y;var n=this._map.options.zoomAnimation&&L.Browser.any3d;L.DomUtil.addClass(this._canvas,"leaflet-zoom-"+(n?"animated":"hide")),this.options.pane.appendChild(this._canvas),t.on(this.getEvents(),this);var i=this._delegate||this;i.onLayerDidMount&&i.onLayerDidMount(),this.needRedraw();var o=this;setTimeout(function(){o._onLayerDidMove()},0)},onRemove:function(t){var e=this._delegate||this;e.onLayerWillUnmount&&e.onLayerWillUnmount(),this.options.pane.removeChild(this._canvas),t.off(this.getEvents(),this),this._canvas=null},addTo:function(t){return t.addLayer(this),this},drawLayer:function(){var t=this._map.getSize(),e=this._map.getBounds(),n=this._map.getZoom(),i=this._map.options.crs.project(this._map.getCenter()),o=this._map.options.crs.project(this._map.containerPointToLatLng(this._map.getSize())),a=this._delegate||this;a.onDrawLayer&&a.onDrawLayer({layer:this,canvas:this._canvas,bounds:e,size:t,zoom:n,center:i,corner:o}),this._frame=null},_setTransform:function(t,e,n){var i=e||new L.Point(0,0);t.style[L.DomUtil.TRANSFORM]=(L.Browser.ie3d?"translate("+i.x+"px,"+i.y+"px)":"translate3d("+i.x+"px,"+i.y+"px,0)")+(n?" scale("+n+")":"")},_animateZoom:function(t){var e=this._map.getZoomScale(t.zoom),n=L.Layer?this._map._latLngToNewLayerPoint(this._map.getBounds().getNorthWest(),t.zoom,t.center):this._map._getCenterOffset(t.center)._multiplyBy(-e).subtract(this._map._getMapPanePos());L.DomUtil.setTransform(this._canvas,n,e)}}),L.canvasLayer=function(t){return new L.CanvasLayer(t)},L.Control.Velocity=L.Control.extend({options:{position:"bottomleft",emptyString:"Unavailable",angleConvention:"bearingCCW",showCardinal:!1,speedUnit:"m/s",directionString:"Direction",speedString:"Speed",onAdd:null,onRemove:null},onAdd:function(t){return this._container=L.DomUtil.create("div","leaflet-control-velocity"),L.DomEvent.disableClickPropagation(this._container),t.on("mousemove",this._onMouseMove,this),this._container.innerHTML=this.options.emptyString,this.options.leafletVelocity.options.onAdd&&this.options.leafletVelocity.options.onAdd(),this._container},onRemove:function(t){t.off("mousemove",this._onMouseMove,this),this.options.leafletVelocity.options.onRemove&&this.options.leafletVelocity.options.onRemove()},vectorToSpeed:function(t,e,n){var i=Math.sqrt(Math.pow(t,2)+Math.pow(e,2));return"k/h"===n?this.meterSec2kilometerHour(i):"kt"===n?this.meterSec2Knots(i):"mph"===n?this.meterSec2milesHour(i):i},vectorToDegrees:function(t,e,n){n.endsWith("CCW")&&(e=0<e?e=-e:Math.abs(e));var i=Math.sqrt(Math.pow(t,2)+Math.pow(e,2)),o=180*Math.atan2(t/i,e/i)/Math.PI+180;return"bearingCW"!==n&&"meteoCCW"!==n||360<=(o+=180)&&(o-=360),o},degreesToCardinalDirection:function(t){var e="";return 0<=t&&t<11.25||348.75<=t?e="N":11.25<=t&&t<33.75?e="NNW":33.75<=t&&t<56.25?e="NW":56.25<=t&&t<78.75?e="WNW":78.25<=t&&t<101.25?e="W":101.25<=t&&t<123.75?e="WSW":123.75<=t&&t<146.25?e="SW":146.25<=t&&t<168.75?e="SSW":168.75<=t&&t<191.25?e="S":191.25<=t&&t<213.75?e="SSE":213.75<=t&&t<236.25?e="SE":236.25<=t&&t<258.75?e="ESE":258.75<=t&&t<281.25?e="E":281.25<=t&&t<303.75?e="ENE":303.75<=t&&t<326.25?e="NE":326.25<=t&&t<348.75&&(e="NNE"),e},meterSec2Knots:function(t){return t/.514},meterSec2kilometerHour:function(t){return 3.6*t},meterSec2milesHour:function(t){return 2.23694*t},_onMouseMove:function(t){var e=this.options.leafletVelocity._map.containerPointToLatLng(L.point(t.containerPoint.x,t.containerPoint.y)),n=this.options.leafletVelocity._windy.interpolatePoint(e.lng,e.lat),i="";if(n&&!isNaN(n[0])&&!isNaN(n[1])&&n[2]){var o=this.vectorToDegrees(n[0],n[1],this.options.angleConvention),a=this.options.showCardinal?" (".concat(this.degreesToCardinalDirection(o),") "):"";i="<strong> ".concat(this.options.velocityType," ").concat(this.options.directionString,": </strong> ").concat(o.toFixed(2),"°").concat(a,", <strong> ").concat(this.options.velocityType," ").concat(this.options.speedString,": </strong> ").concat(this.vectorToSpeed(n[0],n[1],this.options.speedUnit).toFixed(2)," ").concat(this.options.speedUnit)}else i=this.options.emptyString;this._container.innerHTML=i}}),L.Map.mergeOptions({positionControl:!1}),L.Map.addInitHook(function(){this.options.positionControl&&(this.positionControl=new L.Control.MousePosition,this.addControl(this.positionControl))}),L.control.velocity=function(t){return new L.Control.Velocity(t)},L.VelocityLayer=(L.Layer?L.Layer:L.Class).extend({options:{displayValues:!0,displayOptions:{velocityType:"Velocity",position:"bottomleft",emptyString:"No velocity data"},maxVelocity:10,colorScale:null,data:null},_map:null,_canvasLayer:null,_windy:null,_context:null,_timer:0,_mouseControl:null,initialize:function(t){L.setOptions(this,t)},onAdd:function(t){this._paneName=this.options.paneName||"overlayPane";var e=t._panes.overlayPane;t.getPane&&(e=(e=t.getPane(this._paneName))||t.createPane(this._paneName)),this._canvasLayer=L.canvasLayer({pane:e}).delegate(this),this._canvasLayer.addTo(t),this._map=t},onRemove:function(t){this._destroyWind()},setData:function(t){this.options.data=t,this._windy&&(this._windy.setData(t),this._clearAndRestart()),this.fire("load")},setOpacity:function(t){console.log("this._canvasLayer",this._canvasLayer),this._canvasLayer.setOpacity(t)},setOptions:function(t){this.options=Object.assign(this.options,t),t.hasOwnProperty("displayOptions")&&(this.options.displayOptions=Object.assign(this.options.displayOptions,t.displayOptions),this._initMouseHandler(!0)),t.hasOwnProperty("data")&&(this.options.data=t.data),this._windy&&(this._windy.setOptions(t),t.hasOwnProperty("data")&&this._windy.setData(t.data),this._clearAndRestart()),this.fire("load")},onDrawLayer:function(t,e){var n=this;this._windy?this.options.data&&(this._timer&&clearTimeout(n._timer),this._timer=setTimeout(function(){n._startWindy()},750)):this._initWindy(this)},_startWindy:function(){var t=this._map.getBounds(),e=this._map.getSize();this._windy.start([[0,0],[e.x,e.y]],e.x,e.y,[[t._southWest.lng,t._southWest.lat],[t._northEast.lng,t._northEast.lat]])},_initWindy:function(t){var e=Object.assign({canvas:t._canvasLayer._canvas,map:this._map},t.options);this._windy=new Windy(e),this._context=this._canvasLayer._canvas.getContext("2d"),this._canvasLayer._canvas.classList.add("velocity-overlay"),this.onDrawLayer(),this._map.on("dragstart",t._windy.stop),this._map.on("dragend",t._clearAndRestart),this._map.on("zoomstart",t._windy.stop),this._map.on("zoomend",t._clearAndRestart),this._map.on("resize",t._clearWind),this._initMouseHandler(!1)},_initMouseHandler:function(t){if(t&&(this._map.removeControl(this._mouseControl),this._mouseControl=!1),!this._mouseControl&&this.options.displayValues){var e=this.options.displayOptions||{};(e.leafletVelocity=this)._mouseControl=L.control.velocity(e).addTo(this._map)}},_clearAndRestart:function(){this._context&&this._context.clearRect(0,0,3e3,3e3),this._windy&&this._startWindy()},_clearWind:function(){this._windy&&this._windy.stop(),this._context&&this._context.clearRect(0,0,3e3,3e3)},_destroyWind:function(){this._timer&&clearTimeout(this._timer),this._windy&&this._windy.stop(),this._context&&this._context.clearRect(0,0,3e3,3e3),this._mouseControl&&this._map.removeControl(this._mouseControl),this._mouseControl=null,this._windy=null,this._map.removeLayer(this._canvasLayer)}}),L.velocityLayer=function(t){return new L.VelocityLayer(t)};var Windy=function(S){function o(t,e,n,i,o,a){var r=1-t,s=1-e,l=r*s,h=t*s,c=r*e,d=t*e,p=n[0]*l+i[0]*h+o[0]*c+a[0]*d,u=n[1]*l+i[1]*h+o[1]*c+a[1]*d;return[p,u,Math.sqrt(p*p+u*u)]}function d(t){var e=null,n=null;return t.forEach(function(t){switch(t.header.parameterCategory+","+t.header.parameterNumber){case"1,2":case"2,2":e=t;break;case"1,3":case"2,3":n=t;break;default:t}}),function(t,e){var n=t.data,i=e.data;return{header:t.header,data:function(t){return[n[t],i[t]]},interpolate:o}}(e,n)}function a(i,o,t){function a(t,e){var n=i[Math.round(t)];return n&&n[Math.round(e)]||h}a.release=function(){i=[]},a.randomize=function(t){for(var e,n,i=0;null===a(e=Math.round(Math.floor(Math.random()*o.width)+o.x),n=Math.round(Math.floor(Math.random()*o.height)+o.y))[2]&&i++<30;);return t.x=e,t.y=n,t},t(o,a)}function r(t){return t/180*Math.PI}function s(i,s){var e,n,l=(e=x,n=C,R.indexFor=function(t){return Math.max(0,Math.min(R.length-1,Math.round((t-e)/(n-e)*(R.length-1))))},R),h=l.map(function(){return[]}),t=Math.round(i.width*i.height*D);/android|blackberry|iemobile|ipad|iphone|ipod|opera mini|webos/i.test(navigator.userAgent)&&(t*=T);for(var o="rgba(0, 0, 0, ".concat(O,")"),a=[],r=0;r<t;r++)a.push(s.randomize({age:Math.floor(Math.random()*P)+0}));var c=S.canvas.getContext("2d");c.lineWidth=b,c.fillStyle=o,c.globalAlpha=.6;var d=Date.now();!function t(){M=requestAnimationFrame(t);var e=Date.now(),n=e-d;W<n&&(d=e-n%W,h.forEach(function(t){t.length=0}),a.forEach(function(t){t.age>P&&(s.randomize(t).age=0);var e=t.x,n=t.y,i=s(e,n),o=i[2];if(null===o)t.age=P;else{var a=e+i[0],r=n+i[1];null!==s(a,r)[2]?(t.xt=a,t.yt=r,h[l.indexFor(o)].push(t)):(t.x=a,t.y=r)}t.age+=1}),c.globalCompositeOperation="destination-in",c.fillRect(i.x,i.y,i.width,i.height),c.globalCompositeOperation="lighter",c.globalAlpha=0===O?0:.9*O,h.forEach(function(t,e){0<t.length&&(c.beginPath(),c.strokeStyle=l[e],t.forEach(function(t){c.moveTo(t.x,t.y),c.lineTo(t.xt,t.yt),t.x=t.xt,t.y=t.yt}),c.stroke())}))}()}var u,m,p,y,_,f,v,g,w,M,x=S.minVelocity||0,C=S.maxVelocity||10,l=(S.velocityScale||.005)*(Math.pow(window.devicePixelRatio,1/3)||1),P=S.particleAge||90,b=S.lineWidth||1,D=S.particleMultiplier||1/300,T=Math.pow(window.devicePixelRatio,1/3)||1.6,e=S.frameRate||15,W=1e3/e,O=.97,R=S.colorScale||["rgb(36,104, 180)","rgb(60,157, 194)","rgb(128,205,193 )","rgb(151,218,168 )","rgb(198,231,181)","rgb(238,247,217)","rgb(255,238,159)","rgb(252,217,125)","rgb(255,182,100)","rgb(252,150,75)","rgb(250,112,52)","rgb(245,64,32)","rgb(237,45,28)","rgb(220,24,32)","rgb(180,0,35)"],h=[NaN,NaN,null],c=S.data,N=function(t,e){if(!m)return null;var n,i=z(t-y,360)/f,o=(_-e)/v,a=Math.floor(i),r=a+1,s=Math.floor(o),l=s+1;if(n=m[s]){var h=n[a],c=n[r];if(A(h)&&A(c)&&(n=m[l])){var d=n[a],p=n[r];if(A(d)&&A(p))return u.interpolate(i-a,o-s,h,c,d,p)}}return null},A=function(t){return null!=t},z=function(t,e){return t-e*Math.floor(t/e)},E=function(t,e,n,i,o){var a=2*Math.PI,r=e<0?5:-5,s=n<0?5:-5,l=V(n,e+r),h=V(n+s,e),c=Math.cos(n/360*a);return[(l[0]-i)/r/c,(l[1]-o)/r/c,(h[0]-i)/s,(h[1]-o)/s]},V=function(t,e,n){var i=S.map.latLngToContainerPoint(L.latLng(t,e));return[i.x,i.y]},U=function(){F.field&&F.field.release(),M&&cancelAnimationFrame(M)},F={params:S,start:function(e,n,i,t){var o={south:r(t[0][1]),north:r(t[1][1]),east:r(t[1][0]),west:r(t[0][0]),width:n,height:i};U(),function(t,e){var n=!0;t.length<2&&(n=!1),n||console.log("Windy Error: data must have at least two components (u,v)");var i=(u=d(t)).header;if(i.hasOwnProperty("gridDefinitionTemplate")&&0!=i.gridDefinitionTemplate&&(n=!1),n||console.log("Windy Error: Only data with Latitude_Longitude coordinates is supported"),n=!0,y=i.lo1,_=i.la1,f=i.dx,v=i.dy,g=i.nx,w=i.ny,i.hasOwnProperty("scanMode")){var o=i.scanMode.toString(2),a=(o=("0"+o).slice(-8)).split("").map(Number).map(Boolean);a[0]&&(f=-f),a[1]&&(v=-v),a[2]&&(n=!1),a[3]&&(n=!1),a[4]&&(n=!1),a[5]&&(n=!1),a[6]&&(n=!1),a[7]&&(n=!1),n||console.log("Windy Error: Data with scanMode: "+i.scanMode+" is not supported.")}(p=new Date(i.refTime)).setHours(p.getHours()+i.forecastTime),m=[];for(var r=0,s=360<=Math.floor(g*f),l=0;l<w;l++){for(var h=[],c=0;c<g;c++,r++)h[c]=u.data(r);s&&h.push(h[0]),m[l]=h}e({date:p,interpolate:N})}(c,function(t){!function(w,M,t,n){var x={},e=(t.south-t.north)*(t.west-t.east),C=l*Math.pow(e,.4),P=[],i=M.x;function o(t){for(var e,n,i,o,a,r,s,l,h,c,d,p,u,m=[],y=M.y;y<=M.yMax;y+=2){var _=(d=t,p=y,void 0,[(u=S.map.containerPointToLatLng(L.point(d,p))).lng,u.lat]),f=_[0],v=_[1];if(isFinite(f)){var g=w.interpolate(f,v);g&&(e=x,n=f,i=v,o=t,a=y,r=C,void 0,l=(s=g)[0]*r,h=s[1]*r,c=E(e,n,i,o,a),s[0]=c[0]*l+c[2]*h,s[1]=c[1]*l+c[3]*h,g=s,m[y+1]=m[y]=g)}}P[t+1]=P[t]=m}!function t(){for(var e=Date.now();i<M.width;)if(o(i),i+=2,1e3<Date.now()-e)return void setTimeout(t,25);a(P,M,n)}()}(t,function(t,e,n){var i=t[0],o=t[1],a=Math.round(i[0]),r=Math.max(Math.floor(i[1],0),0);Math.min(Math.ceil(o[0],e),e-1);return{x:a,y:r,xMax:e,yMax:Math.min(Math.ceil(o[1],n),n-1),width:e,height:n}}(e,n,i),o,function(t,e){F.field=e,s(t,e)})})},stop:U,createField:a,interpolatePoint:N,setData:function(t){c=t},setOptions:function(t){t.hasOwnProperty("minVelocity")&&(x=t.minVelocity),t.hasOwnProperty("maxVelocity")&&(C=t.maxVelocity),t.hasOwnProperty("velocityScale")&&(l=(t.velocityScale||.005)*(Math.pow(window.devicePixelRatio,1/3)||1)),t.hasOwnProperty("particleAge")&&(P=t.particleAge),t.hasOwnProperty("lineWidth")&&(b=t.lineWidth),t.hasOwnProperty("particleMultiplier")&&(D=t.particleMultiplier),t.hasOwnProperty("opacity")&&(O=+t.opacity),t.hasOwnProperty("frameRate")&&(e=t.frameRate),W=1e3/e}};return F};window.cancelAnimationFrame||(window.cancelAnimationFrame=function(t){clearTimeout(t)});
|
package/worldmap/worldmap.js
CHANGED
|
@@ -110,7 +110,12 @@ var handleData = function(data) {
|
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
if (data.command) { doCommand(data.command); delete data.command; }
|
|
113
|
-
if (data.hasOwnProperty("type") && data.type.indexOf("Feature") === 0) {
|
|
113
|
+
if (data.hasOwnProperty("type") && data.type.indexOf("Feature") === 0) {
|
|
114
|
+
if (data.hasOwnProperty('properties') && data.properties.hasOwnProperty('title')) {
|
|
115
|
+
doGeojson(data.properties.title,data)
|
|
116
|
+
}
|
|
117
|
+
else { doGeojson("geojson",data); }
|
|
118
|
+
}
|
|
114
119
|
else if (data.hasOwnProperty("name")) { setMarker(data); }
|
|
115
120
|
else {
|
|
116
121
|
if (JSON.stringify(data) !== '{}') {
|
|
@@ -593,7 +598,7 @@ map.on('baselayerchange', function(e) {
|
|
|
593
598
|
});
|
|
594
599
|
|
|
595
600
|
function showMapCurrentZoom() {
|
|
596
|
-
//console.log("
|
|
601
|
+
//console.log("ZOOM:",map.getZoom());
|
|
597
602
|
for (var l in layers) {
|
|
598
603
|
if (layers[l].hasOwnProperty("_zoom")) {
|
|
599
604
|
if (map.getZoom() >= clusterAt) {
|
|
@@ -635,12 +640,12 @@ map.on('zoomend', function() {
|
|
|
635
640
|
showMapCurrentZoom();
|
|
636
641
|
window.localStorage.setItem("lastzoom", map.getZoom());
|
|
637
642
|
var b = map.getBounds();
|
|
638
|
-
ws.send(JSON.stringify({action:"bounds", south:b._southWest.lat, west:b._southWest.lng, north:b._northEast.lat, east:b._northEast.lng }));
|
|
643
|
+
ws.send(JSON.stringify({action:"bounds", south:b._southWest.lat, west:b._southWest.lng, north:b._northEast.lat, east:b._northEast.lng, zoom:map.getZoom() }));
|
|
639
644
|
});
|
|
640
645
|
map.on('moveend', function() {
|
|
641
646
|
window.localStorage.setItem("lastpos",JSON.stringify(map.getCenter()));
|
|
642
647
|
var b = map.getBounds();
|
|
643
|
-
ws.send(JSON.stringify({action:"bounds", south:b._southWest.lat, west:b._southWest.lng, north:b._northEast.lat, east:b._northEast.lng }));
|
|
648
|
+
ws.send(JSON.stringify({action:"bounds", south:b._southWest.lat, west:b._southWest.lng, north:b._northEast.lat, east:b._northEast.lng, zoom:map.getZoom() }));
|
|
644
649
|
});
|
|
645
650
|
|
|
646
651
|
//map.on('contextmenu', function(e) {
|
|
@@ -735,7 +740,7 @@ var addBaseMaps = function(maplist,first) {
|
|
|
735
740
|
//console.log("MAPS",first,maplist)
|
|
736
741
|
if (navigator.onLine) {
|
|
737
742
|
var layerlookup = { OSMG:"OSM grey", OSMC:"OSM", OSMH:"OSM Humanitarian", EsriC:"Esri", EsriS:"Esri Satellite",
|
|
738
|
-
EsriT:"Esri Topography", EsriO:"Esri Ocean", EsriDG:"Esri Dark Grey", NatGeo: "National Geographic",
|
|
743
|
+
EsriR:"Esri Relief", EsriT:"Esri Topography", EsriO:"Esri Ocean", EsriDG:"Esri Dark Grey", NatGeo: "National Geographic",
|
|
739
744
|
UKOS:"UK OS OpenData", UKOS45:"UK OS 1919-1947", UKOS00:"UK OS 1900", OpTop:"Open Topo Map",
|
|
740
745
|
HB:"Hike Bike OSM", ST:"Stamen Topography", SW: "Stamen Watercolor", AN:"AutoNavi (Chinese)" }
|
|
741
746
|
|
|
@@ -794,21 +799,24 @@ var addBaseMaps = function(maplist,first) {
|
|
|
794
799
|
if (maplist.indexOf("EsriR")!==-1) {
|
|
795
800
|
basemaps[layerlookup["EsriR"]] = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Shaded_Relief/MapServer/tile/{z}/{y}/{x}', {
|
|
796
801
|
attribution:'Tiles © Esri',
|
|
797
|
-
maxNativeZoom:13
|
|
802
|
+
maxNativeZoom:13,
|
|
803
|
+
maxZoom:16
|
|
798
804
|
});
|
|
799
805
|
}
|
|
800
806
|
|
|
801
807
|
if (maplist.indexOf("EsriO")!==-1) {
|
|
802
808
|
basemaps[layerlookup["EsriO"]] = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/Ocean_Basemap/MapServer/tile/{z}/{y}/{x}', {
|
|
803
809
|
attribution:'Tiles © Esri — Sources: GEBCO, NOAA, CHS, OSU, UNH, CSUMB, National Geographic, DeLorme, NAVTEQ, and Esri',
|
|
804
|
-
maxNativeZoom:
|
|
810
|
+
maxNativeZoom:10,
|
|
811
|
+
maxZoom:13
|
|
805
812
|
});
|
|
806
813
|
}
|
|
807
814
|
|
|
808
815
|
if (maplist.indexOf("EsriDG")!==-1) {
|
|
809
816
|
basemaps[layerlookup["EsriDG"]] = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Dark_Gray_Base/MapServer/tile/{z}/{y}/{x}', {
|
|
810
817
|
attribution: 'Tiles © Esri — Esri, DeLorme, NAVTEQ',
|
|
811
|
-
maxNativeZoom:
|
|
818
|
+
maxNativeZoom:16,
|
|
819
|
+
maxZoom:18
|
|
812
820
|
});
|
|
813
821
|
}
|
|
814
822
|
|
|
@@ -1775,8 +1783,9 @@ function setMarker(data) {
|
|
|
1775
1783
|
opts.size = opts.size || sz;
|
|
1776
1784
|
opts.size = opts.size * (opts.scale || 1);
|
|
1777
1785
|
// escape out any isocodes eg flag symbols
|
|
1778
|
-
var optfields = ["additionalInformation","higherFormation","specialHeadquarters","staffComments","type","uniqueDesignation","speed"];
|
|
1779
|
-
const regex = /\p{Extended_Pictographic}/ug;
|
|
1786
|
+
var optfields = ["additionalInformation","higherFormation","specialHeadquarters","staffComments","type","uniqueDesignation","speed","country"];
|
|
1787
|
+
//const regex = /\p{Extended_Pictographic}/ug;
|
|
1788
|
+
const regex = /(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])/gi;
|
|
1780
1789
|
optfields.forEach(function (item) {
|
|
1781
1790
|
if (opts.hasOwnProperty(item) && regex.test(opts[item])) {
|
|
1782
1791
|
opts[item] = unescape(encodeURIComponent(opts[item]));
|
|
@@ -1980,7 +1989,7 @@ function setMarker(data) {
|
|
|
1980
1989
|
else if (data.heading !== undefined) { track = data.heading; }
|
|
1981
1990
|
else if (data.bearing !== undefined) { track = data.bearing; }
|
|
1982
1991
|
if (track != undefined) { // if there is a heading
|
|
1983
|
-
if (data.speed != null &&
|
|
1992
|
+
if (data.speed != null && data.length === undefined) { // and a speed - lets convert to a leader length
|
|
1984
1993
|
data.length = parseFloat(data.speed || "0") * 60;
|
|
1985
1994
|
var re1 = new RegExp('kn|knot|kt','i');
|
|
1986
1995
|
var re2 = new RegExp('kph|kmh','i');
|
|
@@ -1989,7 +1998,7 @@ function setMarker(data) {
|
|
|
1989
1998
|
else if ( re2.test(""+data.speed) ) { data.length = data.length * 0.44704; }
|
|
1990
1999
|
else if ( re3.test(""+data.speed) ) { data.length = data.length * 0.277778; }
|
|
1991
2000
|
}
|
|
1992
|
-
if (data.length
|
|
2001
|
+
if (data.length !== undefined) {
|
|
1993
2002
|
if (polygons[data.name] != null && !polygons[data.name].hasOwnProperty("_layers")) {
|
|
1994
2003
|
map.removeLayer(polygons[data.name]);
|
|
1995
2004
|
}
|
|
@@ -2449,6 +2458,11 @@ function doCommand(cmd) {
|
|
|
2449
2458
|
else if (cmd.map.url.slice(-4).toLowerCase() === ".pbf") {
|
|
2450
2459
|
overlays[cmd.map.overlay] = VectorTileLayer(cmd.map.url, cmd.map.opt);
|
|
2451
2460
|
}
|
|
2461
|
+
else if (cmd.map.hasOwnProperty("transparentPixels")) {
|
|
2462
|
+
cmd.map.opt.pixelCodes = cmd.map.transparentPixels;
|
|
2463
|
+
cmd.map.opt.matchRGBA = [ 0,0,0,0 ];
|
|
2464
|
+
overlays[cmd.map.overlay] = L.tileLayerPixelFilter(cmd.map.url, cmd.map.opt);
|
|
2465
|
+
}
|
|
2452
2466
|
else {
|
|
2453
2467
|
overlays[cmd.map.overlay] = L.tileLayer(cmd.map.url, cmd.map.opt);
|
|
2454
2468
|
}
|
|
@@ -2500,6 +2514,8 @@ function doCommand(cmd) {
|
|
|
2500
2514
|
// Turn on an existing overlay(s)
|
|
2501
2515
|
if (cmd.hasOwnProperty("showlayer")) {
|
|
2502
2516
|
if (typeof cmd.showlayer === "string") { cmd.showlayer = [ cmd.showlayer ]; }
|
|
2517
|
+
var sn = cmd.showlayer.indexOf("ship nav");
|
|
2518
|
+
if (sn !== -1) { cmd.showlayer[sn] = "ship navigation"; }
|
|
2503
2519
|
for (var i=0; i < cmd.showlayer.length; i++) {
|
|
2504
2520
|
if (overlays.hasOwnProperty(cmd.showlayer[i])) {
|
|
2505
2521
|
map.addLayer(overlays[cmd.showlayer[i]]);
|
|
@@ -2509,6 +2525,8 @@ function doCommand(cmd) {
|
|
|
2509
2525
|
// Turn off an existing overlay(s)
|
|
2510
2526
|
if (cmd.hasOwnProperty("hidelayer")) {
|
|
2511
2527
|
if (typeof cmd.hidelayer === "string") { cmd.hidelayer = [ cmd.hidelayer ]; }
|
|
2528
|
+
var sn = cmd.hidelayer.indexOf("ship nav");
|
|
2529
|
+
if (sn !== -1) { cmd.hidelayer[sn] = "ship navigation"; }
|
|
2512
2530
|
for (var i=0; i < cmd.hidelayer.length; i++) {
|
|
2513
2531
|
if (overlays.hasOwnProperty(cmd.hidelayer[i])) {
|
|
2514
2532
|
map.removeLayer(overlays[cmd.hidelayer[i]]);
|
|
@@ -2563,6 +2581,7 @@ function doCommand(cmd) {
|
|
|
2563
2581
|
|
|
2564
2582
|
// handle any incoming GEOJSON directly - may style badly
|
|
2565
2583
|
function doGeojson(n,g,l,o) {
|
|
2584
|
+
//console.log("GEOJSON",n,g,l,o)
|
|
2566
2585
|
var lay = l || g.name || "unknown";
|
|
2567
2586
|
// if (!basemaps[lay]) {
|
|
2568
2587
|
var opt = { style: function(feature) {
|
|
@@ -2594,12 +2613,29 @@ function doGeojson(n,g,l,o) {
|
|
|
2594
2613
|
return st;
|
|
2595
2614
|
}}
|
|
2596
2615
|
opt.pointToLayer = function (feature, latlng) {
|
|
2597
|
-
var myMarker
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2616
|
+
var myMarker;
|
|
2617
|
+
if (feature.properties.hasOwnProperty("SIDC")) {
|
|
2618
|
+
myMarker = new ms.Symbol( feature.properties.SIDC.toUpperCase(), {
|
|
2619
|
+
uniqueDesignation:unescape(encodeURIComponent(feature.properties.title)) ,
|
|
2620
|
+
country:feature.properties.country,
|
|
2621
|
+
direction:feature.properties.bearing,
|
|
2622
|
+
additionalInformation:feature.properties.modifier,
|
|
2623
|
+
size:24
|
|
2624
|
+
});
|
|
2625
|
+
myMarker = L.icon({
|
|
2626
|
+
iconUrl: myMarker.toDataURL(),
|
|
2627
|
+
iconAnchor: [myMarker.getAnchor().x, myMarker.getAnchor().y],
|
|
2628
|
+
className: "natoicon",
|
|
2629
|
+
});
|
|
2630
|
+
}
|
|
2631
|
+
else {
|
|
2632
|
+
myMarker = L.VectorMarkers.icon({
|
|
2633
|
+
icon: feature.properties["marker-symbol"] || "circle",
|
|
2634
|
+
markerColor: (feature.properties["marker-color"] || "#910000"),
|
|
2635
|
+
prefix: 'fa',
|
|
2636
|
+
iconColor: 'white'
|
|
2637
|
+
});
|
|
2638
|
+
}
|
|
2603
2639
|
if (!feature.properties.hasOwnProperty("title")) {
|
|
2604
2640
|
feature.properties.title = feature.properties["marker-symbol"];
|
|
2605
2641
|
}
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
<script src="leaflet/Leaflet.Coordinates.js"></script>
|
|
43
43
|
<script src="leaflet/leaflet.latlng-graticule.js"></script>
|
|
44
44
|
<script src="leaflet/Semicircle.js"></script>
|
|
45
|
+
<script src="leaflet/L.TileLayer.PixelFilter.js"></script>
|
|
45
46
|
<script src="leaflet/dialog-polyfill.js"></script>
|
|
46
47
|
|
|
47
48
|
<script src="images/emoji.js"></script>
|