PageSourceSearch

https://www.ea2cw.eus/locator/js/Leaflet.Graticule.js

js ea2cw.eus collected 2026-10-06 13:15:01 UTC 18,325 bytes, 521 lines download raw bytes

vendor: 18,325 bytes, lines 1-521
1/**
2*  Create a Canvas as ImageOverlay to draw the Lat/Lon Graticule,
3*  and show the axis tick label on the edge of the map.
4*  Author: [email protected]
5*/
6
7L.LatLngGraticule = L.Layer.extend({
8    options: {
9        showLabel: true,
10        opacity: 1,
11        weight: 0.8,
12        color: '#aaa',
13        font: '12px Verdana',
14        lngLineCurved: 0,
15        latLineCurved: 0,
16        zoomInterval: [
17            {start: 2, end: 2, interval: 40},
18            {start: 3, end: 3, interval: 20},
19            {start: 4, end: 4, interval: 10},
20            {start: 5, end: 7, interval: 5},
21            {start: 8, end: 20, interval: 1}
22        ]
23    },
24
25    initialize: function (options) {
26        L.setOptions(this, options);
27
28        var defaultFontName = 'Verdana';
29        var _ff = this.options.font.split(' ');
30        if (_ff.length < 2) {
31            this.options.font += ' ' + defaultFontName;
32        }
33
34        if (!this.options.fontColor) {
35            this.options.fontColor = this.options.color;
36        }
37
38        if (this.options.zoomInterval) {
39            if (this.options.zoomInterval.latitude) {
40                this.options.latInterval = this.options.zoomInterval.latitude;
41                if (!this.options.zoomInterval.longitude) {
42                    this.options.lngInterval = this.options.zoomInterval.latitude;
43                }
44            }
45            if (this.options.zoomInterval.longitude) {
46                this.options.lngInterval = this.options.zoomInterval.longitude;
47                if (!this.options.zoomInterval.latitude) {
48                    this.options.latInterval = this.options.zoomInterval.longitude;
49                }
50            }
51            if (!this.options.latInterval) {
52                this.options.latInterval = this.options.zoomInterval;
53            }
54            if (!this.options.lngInterval) {
55                this.options.lngInterval = this.options.zoomInterval;
56            }
57        }
58    },
59
60    onAdd: function (map) {
61        this._map = map;
62
63        if (!this._container) {
64            this._initCanvas();
65        }
66
67        map._panes.overlayPane.appendChild(this._container);
68
69        map.on('viewreset', this._reset, this);
70        map.on('move', this._reset, this);
71        map.on('moveend', this._reset, this);
72
73// 		if (map.options.zoomAnimation && L.Browser.any3d) {
74// 			map.on('zoom', this._animateZoom, this);
75// 		}
76
77        this._reset();
78    },
79
80    onRemove: function (map) {
81        map.getPanes().overlayPane.removeChild(this._container);
82
83        map.off('viewreset', this._reset, this);
84        map.off('move', this._reset, this);
85        map.off('moveend', this._reset, this);
86
87// 		if (map.options.zoomAnimation) {
88// 			map.off('zoom', this._animateZoom, this);
89// 		}
90    },
91
92    addTo: function (map) {
93        map.addLayer(this);
94        return this;
95    },
96
97    setOpacity: function (opacity) {
98        this.options.opacity = opacity;
99        this._updateOpacity();
100        return this;
101    },
102
103    bringToFront: function () {
104        if (this._canvas) {
105            this._map._panes.overlayPane.appendChild(this._canvas);
106        }
107        return this;
108    },
109
110    bringToBack: function () {
111        var pane = this._map._panes.overlayPane;
112        if (this._canvas) {
113            pane.insertBefore(this._canvas, pane.firstChild);
114        }
115        return this;
116    },
117
118    getAttribution: function () {
119        return this.options.attribution;
120    },
121
122    _initCanvas: function () {
123        this._container = L.DomUtil.create('div', 'leaflet-image-layer');
124
125        this._canvas = L.DomUtil.create('canvas', '');
126
127        if (this._map.options.zoomAnimation && L.Browser.any3d) {
128            L.DomUtil.addClass(this._canvas, 'leaflet-zoom-animated');
129        } else {
130            L.DomUtil.addClass(this._canvas, 'leaflet-zoom-hide');
131        }
132
133        this._updateOpacity();
134
135        this._container.appendChild(this._canvas);
136
137        L.extend(this._canvas, {
138            onselectstart: L.Util.falseFn,
139            onmousemove: L.Util.falseFn,
140            onload: L.bind(this._onCanvasLoad, this)
141        });
142    },
143
144// 	_animateZoom: function (e) {
145// 		var map = this._map,
146// 			container = this._container,
147// 			canvas = this._canvas,
148// 			zoom = map.getZoom(),
149// 			center = map.getCenter(),
150// 			scale = map.getZoomScale(zoom),
151// 			nw = map.containerPointToLatLng([0, 0]),
152// 			se = map.containerPointToLatLng([canvas.width, canvas.height]),
153//
154// 			topLeft = map._latLngToNewLayerPoint(nw, zoom, center),
155// 			size = map._latLngToNewLayerPoint(se, zoom, center)._subtract(topLeft),
156// 			origin = topLeft._add(size._multiplyBy((1 / 2) * (1 - 1 / scale)));
157//
158// 		L.DomUtil.setTransform(container, origin, scale);
159// 	},
160
161    _reset: function () {
162        var container = this._container,
163            canvas = this._canvas,
164            size = this._map.getSize(),
165            lt = this._map.containerPointToLayerPoint([0, 0]);
166
167        L.DomUtil.setPosition(container, lt);
168
169        container.style.width = size.x + 'px';
170        container.style.height = size.y + 'px';
171
172        canvas.width  = size.x;
173        canvas.height = size.y;
174        canvas.style.width  = size.x + 'px';
175        canvas.style.height = size.y + 'px';
176
177        this.__calcInterval();
178
179        this.__draw(true);
180    },
181
182    _onCanvasLoad: function () {
183        this.fire('load');
184    },
185
186    _updateOpacity: function () {
187        L.DomUtil.setOpacity(this._canvas, this.options.opacity);
188    },
189
190    __format_lat: function(lat) {
191        if (this.options.latFormatTickLabel) {
192            return this.options.latFormatTickLabel(lat);
193        }
194
195        // todo: format type of float
196		 lat = Math.round(lat * 100) / 100; // modified by TK5EP
197        if (lat < 0) {
198            return '' + (lat*-1) + 'S';
199        }
200        else if (lat > 0) {
201            return '' + lat + 'N';
202        }
203        return '' + lat;
204    },
205
206    __format_lng: function(lng) {
207        if (this.options.lngFormatTickLabel) {
208            return this.options.lngFormatTickLabel(lng);
209        }
210
211        // todo: format type of float
212		
213		lng = Math.round(lng * 100) / 100; // modified by TK5EP
214        if (lng > 180) {
215            return '' + (360 - lng) + 'W';
216        }
217        else if (lng > 0 && lng < 180) {
218            return '' + lng + 'E';
219        }
220        else if (lng < 0 && lng > -180) {
221            return '' + (lng*-1) + 'W';
222        }
223        else if (lng == -180) {
224            return '' + (lng*-1);
225        }
226        else if (lng < -180) {
227            return '' + (360 + lng) + 'W';
228        }
229        return '' + lng;
230    },
231
232    __calcInterval: function() {
233        var zoom = this._map.getZoom();
234        if (this._currZoom != zoom) {
235            this._currLngInterval = 0;
236            this._currLatInterval = 0;
237            this._currZoom = zoom;
238        }
239
240        var interv;
241
242        if (!this._currLngInterval) {
243            try {
244                for (var idx in this.options.lngInterval) {
245                    var dict = this.options.lngInterval[idx];
246                    if (dict.start <= zoom) {
247                        if (dict.end && dict.end >= zoom) {
248                            this._currLngInterval = dict.interval;
249                            break;
250                        }
251                    }
252                }
253            }
254            catch(e) {
255                this._currLngInterval = 0;
256            }
257        }
258
259        if (!this._currLatInterval) {
260            try {
261                for (var idx in this.options.latInterval) {
262                    var dict = this.options.latInterval[idx];
263                    if (dict.start <= zoom) {
264                        if (dict.end && dict.end >= zoom) {
265                            this._currLatInterval = dict.interval;
266                            break;
267                        }
268                    }
269                }
270            }
271            catch(e) {
272                this._currLatInterval = 0;
273            }
274        }
275    },
276
277    __draw: function(label) {
278        function _parse_px_to_int(txt) {
279            if (txt.length > 2) {
280                if (txt.charAt(txt.length-2) == 'p') {
281                    txt = txt.substr(0, txt.length-2);
282                }
283            }
284            try {
285                return parseInt(txt, 10);
286            }
287            catch(e) {}
288            return 0;
289        };
290
291        var canvas = this._canvas,
292            map = this._map,
293            curvedLon = this.options.lngLineCurved,
294            curvedLat = this.options.latLineCurved;
295
296        if (L.Browser.canvas && map) {
297            if (!this._currLngInterval || !this._currLatInterval) {
298                this.__calcInterval();
299            }
300
301            var latInterval = this._currLatInterval,
302                lngInterval = this._currLngInterval;
303
304            var ctx = canvas.getContext('2d');
305            ctx.clearRect(0, 0, canvas.width, canvas.height);
306            ctx.lineWidth = this.options.weight;
307            ctx.strokeStyle = this.options.color;
308            ctx.fillStyle = this.options.fontColor;
309
310            if (this.options.font) {
311                ctx.font = this.options.font;
312            }
313            var txtWidth = ctx.measureText('0').width;
314            var txtHeight = 12;
315            try {
316                var _font_size = ctx.font.split(' ')[0];
317                txtHeight = _parse_px_to_int(_font_size);
318            }
319            catch(e) {}
320
321            var ww = canvas.width,
322                hh = canvas.height;
323
324            var lt = map.containerPointToLatLng(L.point(10, 0));
325            var rt = map.containerPointToLatLng(L.point(ww, 0));
326            var rb = map.containerPointToLatLng(L.point(ww, hh));
327
328            var _lat_b = rb.lat,
329                _lat_t = lt.lat;
330            var _lon_l = lt.lng,
331                _lon_r = rt.lng;
332
333            var _point_per_lat = (_lat_t - _lat_b) / (hh * 0.2);
334            if (_point_per_lat < 1) { _point_per_lat = 1; }
335            if (_lat_b < -90) {
336                _lat_b = -90;
337            }
338            else {
339                _lat_b = parseInt(_lat_b - _point_per_lat, 10);
340            }
341
342            if (_lat_t > 90) {
343                _lat_t = 90;
344            }
345            else {
346                _lat_t = parseInt(_lat_t + _point_per_lat, 10);
347            }
348
349            var _point_per_lon = (_lon_r - _lon_l) / (ww * 0.2);
350            if (_point_per_lon < 1) { _point_per_lon = 1; }
351            if (_lon_l > 0 && _lon_r < 0) {
352                _lon_r += 360;
353            }
354            _lon_r = parseInt(_lon_r + _point_per_lon, 10);
355            _lon_l = parseInt(_lon_l - _point_per_lon, 10);
356
357            var ll, latstr, lngstr, _lon_delta = 0.5;
358            function __draw_lat_line(self, lat_tick) {
359                ll = map.latLngToContainerPoint(L.latLng(lat_tick, _lon_l));
360                latstr = self.__format_lat(lat_tick);
361                txtWidth = ctx.measureText(latstr).width;
362
363                if (curvedLat) {
364                    if (typeof(curvedLat) == 'number') {
365                        _lon_delta = curvedLat;
366                    }
367
368                    var __lon_left = _lon_l, __lon_right = _lon_r;
369                    if (ll.x > 0) {
370                        var __lon_left = map.containerPointToLatLng(L.point(0, ll.y));
371                        __lon_left = __lon_left.lng - _point_per_lon;
372                        ll.x = 0;
373                    }
374                    var rr = map.latLngToContainerPoint(L.latLng(lat_tick, __lon_right));
375                    if (rr.x < ww) {
376                        __lon_right = map.containerPointToLatLng(L.point(ww, rr.y));
377                        __lon_right = __lon_right.lng + _point_per_lon;
378                        if (__lon_left > 0 && __lon_right < 0) {
379                            __lon_right += 360;
380                        }
381                    }
382
383                    ctx.beginPath();
384                    ctx.moveTo(ll.x, ll.y);
385                    var _prev_p = null;
386                    for (var j=__lon_left; j<=__lon_right; j+=_lon_delta) {
387                        rr = map.latLngToContainerPoint(L.latLng(lat_tick, j));
388                        ctx.lineTo(rr.x, rr.y);
389
390                        if (self.options.showLabel && label && _prev_p != null) {
391                            if (_prev_p.x < 0 && rr.x >= 0) {
392                                var _s = (rr.x - 0) / (rr.x - _prev_p.x);
393                                var _y = rr.y - ((rr.y - _prev_p.y) * _s);
394                                ctx.fillText(latstr, 0, _y + (txtHeight/2));
395                            }
396                            else if (_prev_p.x <= (ww-txtWidth) && rr.x > (ww-txtWidth)) {
397                                var _s = (rr.x - ww) / (rr.x - _prev_p.x);
398                                var _y = rr.y - ((rr.y - _prev_p.y) * _s);
399                                ctx.fillText(latstr, ww-txtWidth, _y + (txtHeight/2)-2);
400                            }
401                        }
402
403                        _prev_p = {x:rr.x, y:rr.y, lon:j, lat:i};
404                    }
405                    ctx.stroke();
406                }
407                else {
408                    var __lon_right = _lon_r;
409                    var rr = map.latLngToContainerPoint(L.latLng(lat_tick, __lon_right));
410                    if (curvedLon) {
411                        __lon_right = map.containerPointToLatLng(L.point(0, rr.y));
412                        __lon_right = __lon_right.lng;
413                        rr = map.latLngToContainerPoint(L.latLng(lat_tick, __lon_right));
414
415                        var __lon_left = map.containerPointToLatLng(L.point(ww, rr.y));
416                        __lon_left = __lon_left.lng;
417                        ll = map.latLngToContainerPoint(L.latLng(lat_tick, __lon_left));
418                    }
419
420                    ctx.beginPath();
421                    ctx.moveTo(ll.x+1, ll.y);
422                    ctx.lineTo(rr.x-1, rr.y);
423                    ctx.stroke();
424                    if (self.options.showLabel && label) {
425                        var _yy = ll.y + (txtHeight/2)-2;
426                        ctx.fillText(latstr, 0, _yy);
427                        ctx.fillText(latstr, ww-txtWidth, _yy);
428                    }
429                }
430            };
431
432            if (latInterval > 0) {
433                for (var i=latInterval; i<=_lat_t; i+=latInterval) {
434                    if (i >= _lat_b) {
435                        __draw_lat_line(this, i);
436                    }
437                }
438                for (var i=0; i>=_lat_b; i-=latInterval) {
439                    if (i <= _lat_t) {
440                        __draw_lat_line(this, i);
441                    }
442                }
443            }
444
445            function __draw_lon_line(self, lon_tick) {
446                lngstr = self.__format_lng(lon_tick);
447                txtWidth = ctx.measureText(lngstr).width;
448                var bb = map.latLngToContainerPoint(L.latLng(_lat_b, lon_tick));
449
450                if (curvedLon) {
451                    if (typeof(curvedLon) == 'number') {
452                        _lat_delta = curvedLon;
453                    }
454
455                    ctx.beginPath();
456                    ctx.moveTo(bb.x, bb.y);
457                    var _prev_p = null;
458                    for (var j=_lat_b; j<_lat_t; j+=_lat_delta) {
459                        var tt = map.latLngToContainerPoint(L.latLng(j, lon_tick));
460                        ctx.lineTo(tt.x, tt.y);
461
462                        if (self.options.showLabel && label && _prev_p != null) {
463                            if (_prev_p.y > 8 && tt.y <= 8) {
464                                ctx.fillText(lngstr, tt.x - (txtWidth/2), txtHeight);
465                            }
466                            else if (_prev_p.y >= hh && tt.y < hh) {
467                                ctx.fillText(lngstr, tt.x - (txtWidth/2), hh-2);
468                            }
469                        }
470
471                        _prev_p = {x:tt.x, y:tt.y, lon:lon_tick, lat:j};
472                    }
473                    ctx.stroke();
474                }
475                else {
476                    var __lat_top = _lat_t;
477                    var tt = map.latLngToContainerPoint(L.latLng(__lat_top, lon_tick));
478                    if (curvedLat) {
479                        __lat_top = map.containerPointToLatLng(L.point(tt.x, 0));
480                        __lat_top = __lat_top.lat;
481                        if (__lat_top > 90) { __lat_top = 90; }
482                        tt = map.latLngToContainerPoint(L.latLng(__lat_top, lon_tick));
483
484                        var __lat_bottom = map.containerPointToLatLng(L.point(bb.x, hh));
485                        __lat_bottom = __lat_bottom.lat;
486                        if (__lat_bottom < -90) { __lat_bottom = -90; }
487                        bb = map.latLngToContainerPoint(L.latLng(__lat_bottom, lon_tick));
488                    }
489
490                    ctx.beginPath();
491                    ctx.moveTo(tt.x, tt.y+1);
492                    ctx.lineTo(bb.x, bb.y-1);
493                    ctx.stroke();
494
495                    if (self.options.showLabel && label) {
496                        ctx.fillText(lngstr, tt.x - (txtWidth/2), txtHeight+1);
497                        ctx.fillText(lngstr, bb.x - (txtWidth/2), hh-3);
498                    }
499                }
500            };
501
502            if (lngInterval > 0) {
503                for (var i=lngInterval; i<=_lon_r; i+=lngInterval) {
504                    if (i >= _lon_l) {
505                        __draw_lon_line(this, i);
506                    }
507                }
508                for (var i=0; i>=_lon_l; i-=lngInterval) {
509                    if (i <= _lon_r) {
510                        __draw_lon_line(this, i);
511                    }
512                }
513            }
514        }
515    }
516
517});
518
519L.latlngGraticule = function (options) {
520    return new L.LatLngGraticule(options);
521};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.