From e15f94f62b60e8bc6c7af6f03d1e1f2ad6262ea0 Mon Sep 17 00:00:00 2001 From: Mampionona Date: Thu, 3 Jan 2019 10:46:30 +0300 Subject: [PATCH 1/3] Can display Degrees - Decimal minutes --- Leaflet.Graticule.js | 109 +++++++++++++++++++++++++++++++++---------- README.md | 27 +++++++++++ 2 files changed, 112 insertions(+), 24 deletions(-) diff --git a/Leaflet.Graticule.js b/Leaflet.Graticule.js index ecce0c1..02fa070 100755 --- a/Leaflet.Graticule.js +++ b/Leaflet.Graticule.js @@ -13,6 +13,8 @@ L.LatLngGraticule = L.Layer.extend({ font: '12px Verdana', lngLineCurved: 0, latLineCurved: 0, + dmd: false, // Labels: Display Degrees - Decimal Minutes instead of Decimal Degrees + precision: 4, // Lat and Lon precision zoomInterval: [ {start: 2, end: 2, interval: 40}, {start: 3, end: 3, interval: 20}, @@ -187,19 +189,57 @@ L.LatLngGraticule = L.Layer.extend({ L.DomUtil.setOpacity(this._canvas, this.options.opacity); }, + // todo: Decimal degrees to Degrees - Decimal Minutes + __deg_to_dmd: function(deg) { + + var d = Math.floor (deg); + var minfloat = (deg - d) * 60; + var min = minfloat.toFixed(1); + + if (min == 60.0) { + d ++; + min = 0.0; + } + + if (min == 0.0){ + return ('' + d + '°'); + } + + if ((min % 1).toFixed(1) == 0.0) { + min = minfloat.toFixed(0).toString(10).padStart(2, '0'); + } + else { + min = minfloat.toFixed(1).toString(10).padStart(4, '0'); + } + + return ('' + d + '°' + min + "'"); + }, + __format_lat: function(lat) { if (this.options.latFormatTickLabel) { return this.options.latFormatTickLabel(lat); } - // todo: format type of float - if (lat < 0) { - return '' + (lat*-1) + 'S'; + if (this.options.dmd) { + if (lat < 0) { + return this.__deg_to_dmd(lat * -1) + ' S'; + } + else if (lat > 0) { + return this.__deg_to_dmd(lat) + ' N'; + } + return this.__deg_to_dmd(lat); } - else if (lat > 0) { - return '' + lat + 'N'; + else { + // todo: format type of float + if (lat < 0) { + return '' + (lat*-1).toFixed(this.options.precision) + 'S'; + } + else if (lat > 0) { + return '' + lat.toFixed(this.options.precision) + 'N'; + } + return '' + lat.toFixed(this.options.precision); + } - return '' + lat; }, __format_lng: function(lng) { @@ -207,23 +247,44 @@ L.LatLngGraticule = L.Layer.extend({ return this.options.lngFormatTickLabel(lng); } - // todo: format type of float - if (lng > 180) { - return '' + (360 - lng) + 'W'; - } - else if (lng > 0 && lng < 180) { - return '' + lng + 'E'; - } - else if (lng < 0 && lng > -180) { - return '' + (lng*-1) + 'W'; - } - else if (lng == -180) { - return '' + (lng*-1); + if (this.options.dmd) { + // todo: format type of float + if (lng > 180) { + return this.__deg_to_dmd(360 - lng) + ' W'; + } + else if (lng > 0 && lng < 180) { + return this.__deg_to_dmd(lng) + ' E'; + } + else if (lng < 0 && lng > -180) { + return this.__deg_to_dmd(lng*-1) + ' W'; + } + else if (lng == -180) { + return this.__deg_to_dmd(lng*-1); + } + else if (lng < -180) { + return '' + this.__deg_to_dmd(360 + lng) + ' W'; + } + return this.__deg_to_dmd(lng); } - else if (lng < -180) { - return '' + (360 + lng) + 'W'; + else { + // todo: format type of float + if (lng > 180) { + return '' + (360 - lng).toFixed(this.options.precision) + 'W'; + } + else if (lng > 0 && lng < 180) { + return '' + lng.toFixed(this.options.precision) + 'E'; + } + else if (lng < 0 && lng > -180) { + return '' + (lng*-1).toFixed(this.options.precision) + 'W'; + } + else if (lng == -180) { + return '' + (lng*-1).toFixed(this.options.precision); + } + else if (lng < -180) { + return '' + (360 + lng).toFixed(this.options.precision) + 'W'; + } + return '' + lng.toFixed(this.options.precision); } - return '' + lng; }, __calcInterval: function() { @@ -419,7 +480,7 @@ L.LatLngGraticule = L.Layer.extend({ ctx.lineTo(rr.x-1, rr.y); ctx.stroke(); if (self.options.showLabel && label) { - var _yy = ll.y + (txtHeight/2)-2; + var _yy = ll.y - (txtHeight/2) + 2; ctx.fillText(latstr, 0, _yy); ctx.fillText(latstr, ww-txtWidth, _yy); } @@ -490,8 +551,8 @@ L.LatLngGraticule = L.Layer.extend({ ctx.stroke(); if (self.options.showLabel && label) { - ctx.fillText(lngstr, tt.x - (txtWidth/2), txtHeight+1); - ctx.fillText(lngstr, bb.x - (txtWidth/2), hh-3); + ctx.fillText(lngstr, tt.x + 3, txtHeight+1); + ctx.fillText(lngstr, bb.x + 3, hh-3); } } }; diff --git a/README.md b/README.md index 9aaeea9..13ca5bd 100755 --- a/README.md +++ b/README.md @@ -21,6 +21,31 @@ Check out the [demo](https://leaflet.github.io/Leaflet.Graticule/example/). }).addTo(map); ``` +Or + +```javascript + L.latlngGraticule({ + showLabel: true, + zoomInterval: [ + {start: 0, end: 1, interval: 90}, + {start: 2, end: 2, interval: 45}, + {start: 3, end: 3, interval: 10}, + {start: 4, end: 5, interval: 5}, + {start: 6, end: 6, interval: 2}, + {start: 7, end: 7, interval: 1}, + {start: 8, end: 8, interval: (30.0 / 60.0)}, + {start: 9, end: 9, interval: (20.0 / 60.0)}, + {start: 10, end: 10, interval: (10.0 / 60.0)}, + {start: 11, end: 11, interval: (5.0 / 60.0)}, + {start: 12, end: 12, interval: (2.0 / 60.0)}, + {start: 13, end: 13, interval: (1.0 / 60.0)}, + {start: 14, end: 15, interval: (0.5 / 60.0)}, + {start: 16, end: 16, interval: (0.2 / 60.0)}, + {start: 17, end: 18, interval: (0.1 / 60.0)}, + ] + }).addTo(map); +``` + ### Options - **showLabel**: Show the grid tick label at the edges of the map. Default `true` @@ -29,6 +54,8 @@ Check out the [demo](https://leaflet.github.io/Leaflet.Graticule/example/). - **color**: The color of the graticule lines. Default `#aaa` - **font**: Font Style for the tick label. Default `12px Verdana` - **fontColor**: Color of the tick label. Default `#aaa` +- **precision**: Decimal Degrees precision. Default `4` +- **dmd**: Display Degrees and Decimal minutes instead of Decimal Degrees. Default: `false` - **zoomInterval**: Use different intervals in different zoom levels. You can set for both latitude and longitude lines as the example, or set different intervals for latitude and longitude like below: ```javascript zoomInterval: { From 13fe4f9a520896cb1666eb3d400d96d11bb6631f Mon Sep 17 00:00:00 2001 From: Mampionona Date: Thu, 10 Jan 2019 10:53:55 +0300 Subject: [PATCH 2/3] Debug minor issue on W and E labelling when scrolling over the 180th meridian --- Leaflet.Graticule.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Leaflet.Graticule.js b/Leaflet.Graticule.js index 02fa070..11d8003 100755 --- a/Leaflet.Graticule.js +++ b/Leaflet.Graticule.js @@ -262,7 +262,7 @@ L.LatLngGraticule = L.Layer.extend({ return this.__deg_to_dmd(lng*-1); } else if (lng < -180) { - return '' + this.__deg_to_dmd(360 + lng) + ' W'; + return '' + this.__deg_to_dmd(360 + lng) + ' E'; } return this.__deg_to_dmd(lng); } @@ -281,7 +281,7 @@ L.LatLngGraticule = L.Layer.extend({ return '' + (lng*-1).toFixed(this.options.precision); } else if (lng < -180) { - return '' + (360 + lng).toFixed(this.options.precision) + 'W'; + return '' + (360 + lng).toFixed(this.options.precision) + 'E'; } return '' + lng.toFixed(this.options.precision); } From 8be88c2732fe7033f19fc87a4e9550dc53444541 Mon Sep 17 00:00:00 2001 From: Mampionona Date: Mon, 14 Jan 2019 11:23:58 +0300 Subject: [PATCH 3/3] Put format option for labeland modify the docs --- Leaflet.Graticule.js | 164 ++++++++++++++++++++++++++----------------- README.md | 4 +- 2 files changed, 103 insertions(+), 65 deletions(-) diff --git a/Leaflet.Graticule.js b/Leaflet.Graticule.js index 11d8003..c090b0d 100755 --- a/Leaflet.Graticule.js +++ b/Leaflet.Graticule.js @@ -13,7 +13,7 @@ L.LatLngGraticule = L.Layer.extend({ font: '12px Verdana', lngLineCurved: 0, latLineCurved: 0, - dmd: false, // Labels: Display Degrees - Decimal Minutes instead of Decimal Degrees + format: 'dd', // dd: decimal degrees; dmd: degrees - Decimal minutes; dms: Degrees Minutes Seconds; default 'dd' precision: 4, // Lat and Lon precision zoomInterval: [ {start: 2, end: 2, interval: 40}, @@ -189,20 +189,40 @@ L.LatLngGraticule = L.Layer.extend({ L.DomUtil.setOpacity(this._canvas, this.options.opacity); }, + // todo: Decimal degrees to Degrees Minutes Seconds + __deg_to_dms: function(deg) { + var degrees = Math.floor (deg); + var minfloat = (deg - degrees) * 60; + var min = Math.floor(minfloat); + var secfloat = (minfloat-min)*60; + var sec = Math.round(secfloat); + + if (sec==60) { + min++; + sec=0; + } + if (min==60) { + degrees++; + min=0; + } + + return ('' + degrees + '°' + min.toString(10).padStart(2, '0') + "'" + sec.toString(10).padStart(2, '0') + '"'); + }, + // todo: Decimal degrees to Degrees - Decimal Minutes __deg_to_dmd: function(deg) { - var d = Math.floor (deg); - var minfloat = (deg - d) * 60; + var degrees = Math.floor (deg); + var minfloat = (deg - degrees) * 60; var min = minfloat.toFixed(1); if (min == 60.0) { - d ++; + degrees ++; min = 0.0; } if (min == 0.0){ - return ('' + d + '°'); + return ('' + degrees + '°'); } if ((min % 1).toFixed(1) == 0.0) { @@ -212,7 +232,7 @@ L.LatLngGraticule = L.Layer.extend({ min = minfloat.toFixed(1).toString(10).padStart(4, '0'); } - return ('' + d + '°' + min + "'"); + return ('' + degrees + '°' + min + "'"); }, __format_lat: function(lat) { @@ -220,70 +240,83 @@ L.LatLngGraticule = L.Layer.extend({ return this.options.latFormatTickLabel(lat); } - if (this.options.dmd) { - if (lat < 0) { - return this.__deg_to_dmd(lat * -1) + ' S'; - } - else if (lat > 0) { - return this.__deg_to_dmd(lat) + ' N'; - } - return this.__deg_to_dmd(lat); - } - else { - // todo: format type of float - if (lat < 0) { - return '' + (lat*-1).toFixed(this.options.precision) + 'S'; - } - else if (lat > 0) { - return '' + lat.toFixed(this.options.precision) + 'N'; - } - return '' + lat.toFixed(this.options.precision); + switch (this.options.format) { + case 'dmd': + if (lat < 0) { + return this.__deg_to_dmd(lat * -1) + ' S'; + } + else if (lat > 0) { + return this.__deg_to_dmd(lat) + ' N'; + } + return this.__deg_to_dmd(lat); + + case 'dms': + if (lat < 0) { + return this.__deg_to_dms(lat * -1) + ' S'; + } + else if (lat > 0) { + return this.__deg_to_dms(lat) + ' N'; + } + return this.__deg_to_dms(lat); + default: + // todo: format type of float + if (lat < 0) { + return '' + (lat*-1).toFixed(this.options.precision) + ' S'; + } + else if (lat > 0) { + return '' + lat.toFixed(this.options.precision) + ' N'; + } + return '' + lat.toFixed(this.options.precision); } }, - __format_lng: function(lng) { + __format_lng: function(lng, wrapLng) { if (this.options.lngFormatTickLabel) { return this.options.lngFormatTickLabel(lng); } - if (this.options.dmd) { - // todo: format type of float - if (lng > 180) { - return this.__deg_to_dmd(360 - lng) + ' W'; - } - else if (lng > 0 && lng < 180) { - return this.__deg_to_dmd(lng) + ' E'; - } - else if (lng < 0 && lng > -180) { - return this.__deg_to_dmd(lng*-1) + ' W'; - } - else if (lng == -180) { - return this.__deg_to_dmd(lng*-1); - } - else if (lng < -180) { - return '' + this.__deg_to_dmd(360 + lng) + ' E'; - } - return this.__deg_to_dmd(lng); - } - else { - // todo: format type of float - if (lng > 180) { - return '' + (360 - lng).toFixed(this.options.precision) + 'W'; - } - else if (lng > 0 && lng < 180) { - return '' + lng.toFixed(this.options.precision) + 'E'; - } - else if (lng < 0 && lng > -180) { - return '' + (lng*-1).toFixed(this.options.precision) + 'W'; - } - else if (lng == -180) { - return '' + (lng*-1).toFixed(this.options.precision); - } - else if (lng < -180) { - return '' + (360 + lng).toFixed(this.options.precision) + 'E'; - } - return '' + lng.toFixed(this.options.precision); + switch (this.options.format) { + + case 'dmd': + // todo: format type of float + if (lng > 0 && lng < wrapLng[1]) { + return this.__deg_to_dmd(lng) + ' E'; + } + else if (lng < 0 && lng > wrapLng[0]) { + return this.__deg_to_dmd(lng*-1) + ' W'; + } + else if (lng == wrapLng[0]) { + return this.__deg_to_dmd(lng*-1); + } + return this.__deg_to_dmd(lng); + + case 'dms': + // todo: format type of float + if (lng > 0 && lng < wrapLng[1]) { + return this.__deg_to_dms(lng) + ' E'; + } + else if (lng < 0 && lng > wrapLng[0]) { + return this.__deg_to_dms(lng*-1) + ' W'; + } + else if (lng == wrapLng[0]) { + return this.__deg_to_dms(lng*-1); + } + return this.__deg_to_dms(lng); + + default: + // todo: format type of float + if (lng > 0 && lng < wrapLng[1]) { + return '' + lng.toFixed(this.options.precision) + ' E'; + } + else if (lng < 0 && lng > wrapLng[0]) { + return '' + (lng*-1).toFixed(this.options.precision) + ' W'; + } + else if (lng == wrapLng[0]) { + return '' + (lng*-1).toFixed(this.options.precision); + } + return '' + lng.toFixed(this.options.precision); + } }, @@ -501,7 +534,12 @@ L.LatLngGraticule = L.Layer.extend({ } function __draw_lon_line(self, lon_tick) { - lngstr = self.__format_lng(lon_tick); + wrappedlng = map.options.crs.wrapLatLng(L.latLng(0, lon_tick)).lng; + + //Lng range + wrapLng = map.options.crs.wrapLng + + lngstr = self.__format_lng(wrappedlng, wrapLng); txtWidth = ctx.measureText(lngstr).width; var bb = map.latLngToContainerPoint(L.latLng(_lat_b, lon_tick)); diff --git a/README.md b/README.md index 13ca5bd..f9b7eb8 100755 --- a/README.md +++ b/README.md @@ -54,8 +54,8 @@ Or - **color**: The color of the graticule lines. Default `#aaa` - **font**: Font Style for the tick label. Default `12px Verdana` - **fontColor**: Color of the tick label. Default `#aaa` -- **precision**: Decimal Degrees precision. Default `4` -- **dmd**: Display Degrees and Decimal minutes instead of Decimal Degrees. Default: `false` +- **format**: Format of labels. Possible values: `dd` for Decimal Degrees, `dmd` for Degrees Decimal Minutes and `dms` for Degrees Minutes Seconds. Default `dd` +- **precision**: Decimal Degrees precision if format is `dd`. Default `4` - **zoomInterval**: Use different intervals in different zoom levels. You can set for both latitude and longitude lines as the example, or set different intervals for latitude and longitude like below: ```javascript zoomInterval: {