@raruto/leaflet-elevation 2.6.0 → 2.7.0

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.
@@ -1,42 +1,42 @@
1
- .leaflet-ruler {
2
- height: 35px;
3
- width: 35px;
4
- background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAACx0lEQVRIS52VWahOURTHXRSJzBkiJcpYxgeS4oUi90GR4VK6DzcUD3gQIQ8UCXkwlCJRkjJEpqT7oGTMeHONmacyRRl/v9ve2n2d7/vOtevXPmefff5r7bXXXruiSf42gKkToTu0hY/wEk7CnWIyFWX0B/N9OkyF1tANdsEz6AIL4Sl8h8NwEK6nmsUMNGPSalgePFxLfwl2hrG39O1hM8yFobAKpsAGWAE/NJRloBfj++ErnIYesDj1qsjzRsYN2VhwdTPgUaGBkUF0e/D0TxDrRD8ehsFw6AcP4FrgCL17EpsrWAKDUgNtwuQP9FehJsyeSb8FbsOV8O0efVeYHOZV0h8N8w3dWXBOVWpgDwO/oBqc1BxciV7Pg3OJhz66ivPB+PoM8TnqRQPTeNkKfeALtAQ39QYsgE85xNsFz+voFe8AldFALS8DYU3waAd9b5gAv3OKn2HefagK4q64VgPm9k0we0wtN9pN6w+mY9qywqLnWeKXGa/WwHwYFSwrZtw/w9Ic4p5oxesLPG8Qd/UacMf13IE38ArGwN3EQJbnintOHsJsMOaG5Z+4/2vAY282eALd4FvQqoj4Aca3gQfPw1hSPBr4xoNH3bz1EO0D428r9LwpY3vB+nSolOfRQVeg1yOCgXH01pu+GeL+Y1hOwWOYBZlhieJxBU94eA2Lwo9WRw+X8fUEx0PUaPFowKW6Cg+UBc6M6AzrMsR1xtJR1vO4CkNk1TMLJoXBlcHQpvAePW+0eFyBRe45jAbL7fskhqm4MbdGmYruUU94l8zNfIyl4hhfLQteHqaiLYq7J4YlipvnXkgWRotgyRYNWB4st6bpizLiHsiO4H1gMrhnRVtarpcxy0vd+9eLPMvzhuMf1E7QmyC78xrQmDk+BC6Am98CLoKXi/dvWll1xjvjeAkD9YVXpkJ6ae7/BOPus4b+p9X9BdB/zv8zawwXAAAAAElFTkSuQmCC"); /* <div>Icons made by <a href="http://www.freepik.com" title="Freepik">Freepik</a> from <a href="http://www.flaticon.com" title="Flaticon">www.flaticon.com</a> is licensed by <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a></div> */
5
- background-repeat: no-repeat;
6
- background-position: center;
7
- }
8
- .leaflet-ruler-clicked,
9
- .leaflet-ruler:hover {
10
- background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAE/ElEQVRIS6WVeWwUVRzHfzOzs7Pdi+7Rdq/ubrH0sNaKBFMCSEvBQLivFkhAE8GDYAyHATWgETUoMZ7BGCMBNKYiQbTKpYQKBqKlWmBbadmW7bbbFjv0mu2eM298M5SlpS3U+LL/zL6Zz/f7vr/3e4+AsQ6j80EgxTkKhGwkQRqQiLp5UtEOSDwOXf660TDEPfkGR75RTT8VF1EpJRJ6LsbrVuaZg2YtrWND8WD5FVajV9IcTyCOoYhv2QgcgE5fzWDmaAKU0eHa3RMStszNMqIdM+zUY3YdPFvRCG+VOCFFQ0N3mIfNJ3ywb3Em/BHgYNeZFnTc20OOU1Efd7eZtwBUxyWh4QLJGS6jFv04MU2bNWeCQRnoi8L7czPuG+RLJ31g0Smhsqk3dqGVa7wZZOZBb/31oQKm8ZMZRbxyU6FV9XaJmyQGZsNxBD/Ud8FXNWy/rzci9ER4Spqa5tYrit3jmNI8M2DnCRNvnm1Bu35tjcR4lH1HIDtbp+2NNuSmqCyTrBr4dMEDuH4A754LCLvOtQo44zouKp7hQagGIK+CIFgoipqPEHru6OocWJhtlAWk6GZ8cSXs64sd49qbSxMCaenu7+ZkGuftW5JJSy/FBARlh+vDF1tDfWEerYWullNDcjK5c9Q0Or/jcad++3SbbP8ueBn+S7glkOIsNTDUQf+mRxmtkoIIj6Bgb024hYtVhGPK9dDl7RsJvhPDtw3AcWzYuSd8vTcqOS8DrcUIKsUiWcDgyKghRLFgZ1E6vFhohfXfN8YP1bFVfW3N0/E0Ggu8CMNxfY9z7b5SCU4o6dMkhc4RYM61aulwU8fWSSqaIqEqEIRZBzzBSCg+HoIdncPglHgBG9ENdj4inEAXhZuBdQSYXBuWZOnfOLI61yTB1ld4Y1/+xe6Ndvo33Q+ON5Rc0GHOB+DS6gmF2XF6dkZy0eeLM8lU3EDGd6qiQRAnQnvz3wkBXFANdr5jkHMJXrS/NtTIRk5yN3wrErEMgsuNpkp13ViRZ0zdOtUOWiUJ2R/WxPibfmYk+Mp8E/XCT01y4y0/1HBfuCygMDljVzYW0DnmJKhuC8Lsg7WB7kCzQxa4y7nUF08euQblHlZMoqij93J+2yBBpzgjlzcUMJLAmeu9sOjrq+1cR7PtNvzVYrv+5WkOUvpAiqUYx+JlI6cwfPlosQyuHcGYnYECq9r2AV62O5mB9PcuItxjj2ho6uz/hcsRESbH4TX5qQv3LsigNbjJ7Huq+tkIT75enM4Mdx76mbvhXzYW54mIwOBeNd2l+eTs03nyYYIPqrhaSVGbC213xfLf4fIKAB9yqp4IW/VMvtKqVYJJrUhEeCdzGS5lbki22Wu5btYg0IwV2hrYIb0ywoN8VCTbXadDUTRz/9IJsCrfLL82CP7LQCyGcVab56HColQkCKL3ctWxTs/5+WMSAHwPGBih0rNxotqGL42R4DqLpebhKTNta7fvgWBfN7yybIoQjYdzoLPVey+RxHFtdrhfy05J2laxKjep5EAd3oqhhHNtqrm6YOoT6RKcIOXSwEdb1ojXLv35fDRQ99mYBKR6GOyu3zBhcowXTvR3+JdCWhqjVhk9FEW7Z5Wtw1vuFlwatb9XQmuD51J/MFQ+qgAheIdemSl5FoDgOuhs3o0/4vWOKcZkh/4bEJFKxAMA/6QhgsjzAvrH3+SXn0YZAinU/wuTosgK53+p+wAAAABJRU5ErkJggg=="); /* <div>Icons made by <a href="http://www.freepik.com" title="Freepik">Freepik</a> from <a href="http://www.flaticon.com" title="Flaticon">www.flaticon.com</a> is licensed by <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a></div> */
11
- }
12
- .leaflet-ruler-clicked {
13
- height: 35px;
14
- width: 35px;
15
- background-repeat: no-repeat;
16
- background-position: center;
17
- border-color: chartreuse !important;
18
- }
19
- .leaflet-bar.leaflet-ruler {
20
- background-color: #ffffff;
21
- }
22
- .leaflet-control.leaflet-ruler {
23
- cursor: pointer;
24
- }
25
- .result-tooltip {
26
- background-color: white;
27
- border-width: medium;
28
- border-color: #de0000;
29
- font-size: smaller;
30
- }
31
- .moving-tooltip {
32
- background-color: rgba(255, 255, 255, .7);
33
- background-clip: padding-box;
34
- opacity: 0.5;
35
- border: dotted;
36
- border-color: red;
37
- font-size: smaller;
38
- }
39
- .plus-length {
40
- padding-left: 45px;
41
- }
1
+ .leaflet-ruler {
2
+ height: 35px;
3
+ width: 35px;
4
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAACx0lEQVRIS52VWahOURTHXRSJzBkiJcpYxgeS4oUi90GR4VK6DzcUD3gQIQ8UCXkwlCJRkjJEpqT7oGTMeHONmacyRRl/v9ve2n2d7/vOtevXPmefff5r7bXXXruiSf42gKkToTu0hY/wEk7CnWIyFWX0B/N9OkyF1tANdsEz6AIL4Sl8h8NwEK6nmsUMNGPSalgePFxLfwl2hrG39O1hM8yFobAKpsAGWAE/NJRloBfj++ErnIYesDj1qsjzRsYN2VhwdTPgUaGBkUF0e/D0TxDrRD8ehsFw6AcP4FrgCL17EpsrWAKDUgNtwuQP9FehJsyeSb8FbsOV8O0efVeYHOZV0h8N8w3dWXBOVWpgDwO/oBqc1BxciV7Pg3OJhz66ivPB+PoM8TnqRQPTeNkKfeALtAQ39QYsgE85xNsFz+voFe8AldFALS8DYU3waAd9b5gAv3OKn2HefagK4q64VgPm9k0we0wtN9pN6w+mY9qywqLnWeKXGa/WwHwYFSwrZtw/w9Ic4p5oxesLPG8Qd/UacMf13IE38ArGwN3EQJbnintOHsJsMOaG5Z+4/2vAY282eALd4FvQqoj4Aca3gQfPw1hSPBr4xoNH3bz1EO0D428r9LwpY3vB+nSolOfRQVeg1yOCgXH01pu+GeL+Y1hOwWOYBZlhieJxBU94eA2Lwo9WRw+X8fUEx0PUaPFowKW6Cg+UBc6M6AzrMsR1xtJR1vO4CkNk1TMLJoXBlcHQpvAePW+0eFyBRe45jAbL7fskhqm4MbdGmYruUU94l8zNfIyl4hhfLQteHqaiLYq7J4YlipvnXkgWRotgyRYNWB4st6bpizLiHsiO4H1gMrhnRVtarpcxy0vd+9eLPMvzhuMf1E7QmyC78xrQmDk+BC6Am98CLoKXi/dvWll1xjvjeAkD9YVXpkJ6ae7/BOPus4b+p9X9BdB/zv8zawwXAAAAAElFTkSuQmCC"); /* <div>Icons made by <a href="http://www.freepik.com" title="Freepik">Freepik</a> from <a href="http://www.flaticon.com" title="Flaticon">www.flaticon.com</a> is licensed by <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a></div> */
5
+ background-repeat: no-repeat;
6
+ background-position: center;
7
+ }
8
+ .leaflet-ruler-clicked,
9
+ .leaflet-ruler:hover {
10
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAE/ElEQVRIS6WVeWwUVRzHfzOzs7Pdi+7Rdq/ubrH0sNaKBFMCSEvBQLivFkhAE8GDYAyHATWgETUoMZ7BGCMBNKYiQbTKpYQKBqKlWmBbadmW7bbbFjv0mu2eM298M5SlpS3U+LL/zL6Zz/f7vr/3e4+AsQ6j80EgxTkKhGwkQRqQiLp5UtEOSDwOXf660TDEPfkGR75RTT8VF1EpJRJ6LsbrVuaZg2YtrWND8WD5FVajV9IcTyCOoYhv2QgcgE5fzWDmaAKU0eHa3RMStszNMqIdM+zUY3YdPFvRCG+VOCFFQ0N3mIfNJ3ywb3Em/BHgYNeZFnTc20OOU1Efd7eZtwBUxyWh4QLJGS6jFv04MU2bNWeCQRnoi8L7czPuG+RLJ31g0Smhsqk3dqGVa7wZZOZBb/31oQKm8ZMZRbxyU6FV9XaJmyQGZsNxBD/Ud8FXNWy/rzci9ER4Spqa5tYrit3jmNI8M2DnCRNvnm1Bu35tjcR4lH1HIDtbp+2NNuSmqCyTrBr4dMEDuH4A754LCLvOtQo44zouKp7hQagGIK+CIFgoipqPEHru6OocWJhtlAWk6GZ8cSXs64sd49qbSxMCaenu7+ZkGuftW5JJSy/FBARlh+vDF1tDfWEerYWullNDcjK5c9Q0Or/jcad++3SbbP8ueBn+S7glkOIsNTDUQf+mRxmtkoIIj6Bgb024hYtVhGPK9dDl7RsJvhPDtw3AcWzYuSd8vTcqOS8DrcUIKsUiWcDgyKghRLFgZ1E6vFhohfXfN8YP1bFVfW3N0/E0Ggu8CMNxfY9z7b5SCU4o6dMkhc4RYM61aulwU8fWSSqaIqEqEIRZBzzBSCg+HoIdncPglHgBG9ENdj4inEAXhZuBdQSYXBuWZOnfOLI61yTB1ld4Y1/+xe6Ndvo33Q+ON5Rc0GHOB+DS6gmF2XF6dkZy0eeLM8lU3EDGd6qiQRAnQnvz3wkBXFANdr5jkHMJXrS/NtTIRk5yN3wrErEMgsuNpkp13ViRZ0zdOtUOWiUJ2R/WxPibfmYk+Mp8E/XCT01y4y0/1HBfuCygMDljVzYW0DnmJKhuC8Lsg7WB7kCzQxa4y7nUF08euQblHlZMoqij93J+2yBBpzgjlzcUMJLAmeu9sOjrq+1cR7PtNvzVYrv+5WkOUvpAiqUYx+JlI6cwfPlosQyuHcGYnYECq9r2AV62O5mB9PcuItxjj2ho6uz/hcsRESbH4TX5qQv3LsigNbjJ7Huq+tkIT75enM4Mdx76mbvhXzYW54mIwOBeNd2l+eTs03nyYYIPqrhaSVGbC213xfLf4fIKAB9yqp4IW/VMvtKqVYJJrUhEeCdzGS5lbki22Wu5btYg0IwV2hrYIb0ywoN8VCTbXadDUTRz/9IJsCrfLL82CP7LQCyGcVab56HColQkCKL3ctWxTs/5+WMSAHwPGBih0rNxotqGL42R4DqLpebhKTNta7fvgWBfN7yybIoQjYdzoLPVey+RxHFtdrhfy05J2laxKjep5EAd3oqhhHNtqrm6YOoT6RKcIOXSwEdb1ojXLv35fDRQ99mYBKR6GOyu3zBhcowXTvR3+JdCWhqjVhk9FEW7Z5Wtw1vuFlwatb9XQmuD51J/MFQ+qgAheIdemSl5FoDgOuhs3o0/4vWOKcZkh/4bEJFKxAMA/6QhgsjzAvrH3+SXn0YZAinU/wuTosgK53+p+wAAAABJRU5ErkJggg=="); /* <div>Icons made by <a href="http://www.freepik.com" title="Freepik">Freepik</a> from <a href="http://www.flaticon.com" title="Flaticon">www.flaticon.com</a> is licensed by <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a></div> */
11
+ }
12
+ .leaflet-ruler-clicked {
13
+ height: 35px;
14
+ width: 35px;
15
+ background-repeat: no-repeat;
16
+ background-position: center;
17
+ border-color: chartreuse !important;
18
+ }
19
+ .leaflet-bar.leaflet-ruler {
20
+ background-color: #ffffff;
21
+ }
22
+ .leaflet-control.leaflet-ruler {
23
+ cursor: pointer;
24
+ }
25
+ .result-tooltip {
26
+ background-color: white;
27
+ border-width: medium;
28
+ border-color: #de0000;
29
+ font-size: smaller;
30
+ }
31
+ .moving-tooltip {
32
+ background-color: rgba(255, 255, 255, .7);
33
+ background-clip: padding-box;
34
+ opacity: 0.5;
35
+ border: dotted;
36
+ border-color: red;
37
+ font-size: smaller;
38
+ }
39
+ .plus-length {
40
+ padding-left: 45px;
41
+ }
42
42
 
@@ -1,183 +1,183 @@
1
- /*
2
- * Copyright (c) 2022, GPL-3.0+ Project, Raruto
3
- *
4
- * This file is free software: you may copy, redistribute and/or modify it
5
- * under the terms of the GNU General Public License as published by the
6
- * Free Software Foundation, either version 2 of the License, or (at your
7
- * option) any later version.
8
- *
9
- * This file is distributed in the hope that it will be useful, but
10
- * WITHOUT ANY WARRANTY; without even the implied warranty of
11
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
- * General Public License for more details.
13
- *
14
- * You should have received a copy of the GNU General Public License
15
- * along with this program. If not, see .
16
- *
17
- * This file incorporates work covered by the following copyright and
18
- * permission notice:
19
- *
20
- * Copyright (c) 2017 Goker Tanrisever
21
- *
22
- * Permission to use, copy, modify, and/or distribute this software
23
- * for any purpose with or without fee is hereby granted, provided
24
- * that the above copyright notice and this permission notice appear
25
- * in all copies.
26
- *
27
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
28
- * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
29
- * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
30
- * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
31
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
32
- * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
33
- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
34
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
35
- */
36
-
37
- L.Control.Ruler = L.Control.extend({
38
- options: {
39
- position: 'topright',
40
- circleMarker: {
41
- color: 'red',
42
- radius: 2,
43
- },
44
- lineStyle: {
45
- color: 'red',
46
- dashArray: '1,6'
47
- },
48
- lengthUnit: {
49
- display: 'km',
50
- decimal: 2,
51
- factor: 0.001, // meters -> kilometers
52
- label: 'Distance:'
53
- },
54
- angleUnit: {
55
- display: '&deg;',
56
- decimal: 2,
57
- factor: 360,
58
- label: 'Bearing:'
59
- }
60
- },
61
- initialize: function (options) {
62
- L.setOptions(this, options);
63
- this._layers = L.layerGroup();
64
- this._enabled = false;
65
- },
66
- onAdd: function (map) {
67
- this._defaultCursor = map._container.style.cursor;
68
- this._map = map;
69
- let container = L.DomUtil.create('div', 'leaflet-bar');
70
- container.classList.add('leaflet-ruler');
71
- L.DomEvent.disableClickPropagation(container);
72
- L.DomEvent.on(container, 'click', this._toggleMeasure, this);
73
- return this._container = container;
74
- },
75
- onRemove: function () {
76
- L.DomEvent.off(this._container, 'click', this._toggleMeasure, this);
77
- },
78
- _attachMouseEvents: function () {
79
- let map = this._map;
80
- map.doubleClickZoom.disable();
81
- L.DomEvent.on(map._container, 'keydown', this._escape, this);
82
- L.DomEvent.on(map._container, 'dblclick', this._closePath, this);
83
- map._container.style.cursor = 'crosshair';
84
- map.on('click', this._addPoint, this);
85
- map.on('mousemove', this._moving, this);
86
- },
87
- _removeMouseEvents: function () {
88
- let map = this._map;
89
- map.doubleClickZoom.enable();
90
- L.DomEvent.off(map._container, 'keydown', this._escape, this);
91
- L.DomEvent.off(map._container, 'dblclick', this._closePath, this);
92
- map._container.style.cursor = this._defaultCursor;
93
- map.off('click', this._addPoint, this);
94
- map.off('mousemove', this._moving, this);
95
- },
96
- _disable: function () {
97
- this._enabled = false;
98
- this._container.classList.remove("leaflet-ruler-clicked");
99
- this._layers.remove().clearLayers();
100
- this._latlngs = [];
101
- this._totalLength = 0;
102
- this._removeMouseEvents();
103
- },
104
- _enable: function () {
105
- this._enabled = true;
106
- this._container.classList.add("leaflet-ruler-clicked");
107
- this._circles = L.featureGroup().addTo(this._layers);
108
- this._polyline = L.polyline([], this.options.lineStyle).addTo(this._layers);
109
- this._layers.addTo(this._map);
110
- this._latlngs = [];
111
- this._totalLength = 0;
112
- this._attachMouseEvents();
113
- },
114
- _toggleMeasure: function () {
115
- this._enabled ? this._disable() : this._enable();
116
- },
117
- _drawTooltip: function (latlng, layer, incremental) {
118
- let lastClick = this._latlngs[this._latlngs.length - 1] ?? latlng;
119
- let bearing = this._calculateBearing(lastClick, latlng);
120
- let distance = lastClick.distanceTo(latlng) * this.options.lengthUnit.factor;
121
- let accumulated = this._totalLength + distance;
122
- let totalLength = accumulated.toFixed(this.options.lengthUnit.decimal);
123
- let plusLength = incremental ? '<br><div class="plus-length">(+' + distance.toFixed(this.options.lengthUnit.decimal) + ')</div>' : '';
124
- this._totalLength = incremental ? this._totalLength : accumulated;
125
- if (!layer.getTooltip()) layer.bindTooltip('', incremental ? { direction: "auto", sticky: true, offset: L.point(0, -40), className: 'moving-tooltip' } : { permanent: true, className: 'result-tooltip' }).openTooltip();
126
- layer.setLatLng(latlng).setTooltipContent('<b>' + this.options.angleUnit.label + '</b>&nbsp;' + bearing.toFixed(this.options.angleUnit.decimal) + '&nbsp;' + this.options.angleUnit.display + '<br><b>' + this.options.lengthUnit.label + '</b>&nbsp;' + totalLength + '&nbsp;' + this.options.lengthUnit.display + plusLength);
127
- },
128
- _addPoint: function (e) {
129
- let latlng = e.latlng || e;
130
- let point = L.circleMarker(latlng, this.options.circleMarker).addTo(this._circles);
131
- this._polyline.addLatLng(latlng);
132
- if(this._latlngs.length && !latlng.equals(this._latlngs[this._latlngs.length - 1])){
133
- this._drawTooltip(latlng, point, false);
134
- }
135
- this._latlngs.push(latlng);
136
- },
137
- _moving: function (e) {
138
- if (this._latlngs.length) {
139
- let lastCLick = this._latlngs[this._latlngs.length - 1];
140
- if (!this._tempLine) this._tempLine = L.polyline([], this.options.lineStyle).addTo(this._map);
141
- if (!this._tempPoint) this._tempPoint = L.circleMarker(e.latlng, this.options.circleMarker).addTo(this._map);
142
- this._tempLine.setLatLngs([lastCLick, e.latlng]);
143
- this._drawTooltip(e.latlng, this._tempPoint, true);
144
- L.DomEvent.off(this._container, 'click', this._toggleMeasure, this);
145
- }
146
- },
147
- _escape: function (e) {
148
- if (e.keyCode === 27) {
149
- if (this._latlngs.length) {
150
- this._closePath();
151
- } else {
152
- this._enabled = true;
153
- this._toggleMeasure();
154
- }
155
- }
156
- },
157
- _calculateBearing: function (start, end) {
158
- const toRad = L.DomUtil.DEG_TO_RAD;
159
- const toDeg = (this.options.angleUnit.factor / 2) / Math.PI;
160
- let y = Math.sin((end.lng - start.lng) * toRad) * Math.cos(end.lat * toRad);
161
- let x = Math.cos(start.lat * toRad) * Math.sin(end.lat * toRad) - Math.sin(start.lat * toRad) * Math.cos(end.lat * toRad) * Math.cos((end.lng - start.lng) * toRad);
162
- return (Math.atan2(y, x) * toDeg + this.options.angleUnit.factor) % this.options.angleUnit.factor;
163
- },
164
- _closePath: function () {
165
- if (this._tempLine) {
166
- this._tempLine.remove();
167
- this._tempLine = null;
168
- }
169
- if (this._tempPoint) {
170
- this._tempPoint.remove();
171
- this._tempLine = null;
172
- }
173
- if (this._latlngs.length <= 1) {
174
- this._circles.remove();
175
- }
176
- this._enabled = false;
177
- L.DomEvent.on(this._container, 'click', this._toggleMeasure, this);
178
- this._toggleMeasure();
179
- },
180
- });
181
- L.control.ruler = function (options) {
182
- return new L.Control.Ruler(options);
1
+ /*
2
+ * Copyright (c) 2022, GPL-3.0+ Project, Raruto
3
+ *
4
+ * This file is free software: you may copy, redistribute and/or modify it
5
+ * under the terms of the GNU General Public License as published by the
6
+ * Free Software Foundation, either version 2 of the License, or (at your
7
+ * option) any later version.
8
+ *
9
+ * This file is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program. If not, see .
16
+ *
17
+ * This file incorporates work covered by the following copyright and
18
+ * permission notice:
19
+ *
20
+ * Copyright (c) 2017 Goker Tanrisever
21
+ *
22
+ * Permission to use, copy, modify, and/or distribute this software
23
+ * for any purpose with or without fee is hereby granted, provided
24
+ * that the above copyright notice and this permission notice appear
25
+ * in all copies.
26
+ *
27
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
28
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
29
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
30
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
31
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
32
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
33
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
34
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
35
+ */
36
+
37
+ L.Control.Ruler = L.Control.extend({
38
+ options: {
39
+ position: 'topright',
40
+ circleMarker: {
41
+ color: 'red',
42
+ radius: 2,
43
+ },
44
+ lineStyle: {
45
+ color: 'red',
46
+ dashArray: '1,6'
47
+ },
48
+ lengthUnit: {
49
+ display: 'km',
50
+ decimal: 2,
51
+ factor: 0.001, // meters -> kilometers
52
+ label: 'Distance:'
53
+ },
54
+ angleUnit: {
55
+ display: '&deg;',
56
+ decimal: 2,
57
+ factor: 360,
58
+ label: 'Bearing:'
59
+ }
60
+ },
61
+ initialize: function (options) {
62
+ L.setOptions(this, options);
63
+ this._layers = L.layerGroup();
64
+ this._enabled = false;
65
+ },
66
+ onAdd: function (map) {
67
+ this._defaultCursor = map._container.style.cursor;
68
+ this._map = map;
69
+ let container = L.DomUtil.create('div', 'leaflet-bar');
70
+ container.classList.add('leaflet-ruler');
71
+ L.DomEvent.disableClickPropagation(container);
72
+ L.DomEvent.on(container, 'click', this._toggleMeasure, this);
73
+ return this._container = container;
74
+ },
75
+ onRemove: function () {
76
+ L.DomEvent.off(this._container, 'click', this._toggleMeasure, this);
77
+ },
78
+ _attachMouseEvents: function () {
79
+ let map = this._map;
80
+ map.doubleClickZoom.disable();
81
+ L.DomEvent.on(map._container, 'keydown', this._escape, this);
82
+ L.DomEvent.on(map._container, 'dblclick', this._closePath, this);
83
+ map._container.style.cursor = 'crosshair';
84
+ map.on('click', this._addPoint, this);
85
+ map.on('mousemove', this._moving, this);
86
+ },
87
+ _removeMouseEvents: function () {
88
+ let map = this._map;
89
+ map.doubleClickZoom.enable();
90
+ L.DomEvent.off(map._container, 'keydown', this._escape, this);
91
+ L.DomEvent.off(map._container, 'dblclick', this._closePath, this);
92
+ map._container.style.cursor = this._defaultCursor;
93
+ map.off('click', this._addPoint, this);
94
+ map.off('mousemove', this._moving, this);
95
+ },
96
+ _disable: function () {
97
+ this._enabled = false;
98
+ this._container.classList.remove("leaflet-ruler-clicked");
99
+ this._layers.remove().clearLayers();
100
+ this._latlngs = [];
101
+ this._totalLength = 0;
102
+ this._removeMouseEvents();
103
+ },
104
+ _enable: function () {
105
+ this._enabled = true;
106
+ this._container.classList.add("leaflet-ruler-clicked");
107
+ this._circles = L.featureGroup().addTo(this._layers);
108
+ this._polyline = L.polyline([], this.options.lineStyle).addTo(this._layers);
109
+ this._layers.addTo(this._map);
110
+ this._latlngs = [];
111
+ this._totalLength = 0;
112
+ this._attachMouseEvents();
113
+ },
114
+ _toggleMeasure: function () {
115
+ this._enabled ? this._disable() : this._enable();
116
+ },
117
+ _drawTooltip: function (latlng, layer, incremental) {
118
+ let lastClick = this._latlngs[this._latlngs.length - 1] ?? latlng;
119
+ let bearing = this._calculateBearing(lastClick, latlng);
120
+ let distance = lastClick.distanceTo(latlng) * this.options.lengthUnit.factor;
121
+ let accumulated = this._totalLength + distance;
122
+ let totalLength = accumulated.toFixed(this.options.lengthUnit.decimal);
123
+ let plusLength = incremental ? '<br><div class="plus-length">(+' + distance.toFixed(this.options.lengthUnit.decimal) + ')</div>' : '';
124
+ this._totalLength = incremental ? this._totalLength : accumulated;
125
+ if (!layer.getTooltip()) layer.bindTooltip('', incremental ? { direction: "auto", sticky: true, offset: L.point(0, -40), className: 'moving-tooltip' } : { permanent: true, className: 'result-tooltip' }).openTooltip();
126
+ layer.setLatLng(latlng).setTooltipContent('<b>' + this.options.angleUnit.label + '</b>&nbsp;' + bearing.toFixed(this.options.angleUnit.decimal) + '&nbsp;' + this.options.angleUnit.display + '<br><b>' + this.options.lengthUnit.label + '</b>&nbsp;' + totalLength + '&nbsp;' + this.options.lengthUnit.display + plusLength);
127
+ },
128
+ _addPoint: function (e) {
129
+ let latlng = e.latlng || e;
130
+ let point = L.circleMarker(latlng, this.options.circleMarker).addTo(this._circles);
131
+ this._polyline.addLatLng(latlng);
132
+ if(this._latlngs.length && !latlng.equals(this._latlngs[this._latlngs.length - 1])){
133
+ this._drawTooltip(latlng, point, false);
134
+ }
135
+ this._latlngs.push(latlng);
136
+ },
137
+ _moving: function (e) {
138
+ if (this._latlngs.length) {
139
+ let lastCLick = this._latlngs[this._latlngs.length - 1];
140
+ if (!this._tempLine) this._tempLine = L.polyline([], this.options.lineStyle).addTo(this._map);
141
+ if (!this._tempPoint) this._tempPoint = L.circleMarker(e.latlng, this.options.circleMarker).addTo(this._map);
142
+ this._tempLine.setLatLngs([lastCLick, e.latlng]);
143
+ this._drawTooltip(e.latlng, this._tempPoint, true);
144
+ L.DomEvent.off(this._container, 'click', this._toggleMeasure, this);
145
+ }
146
+ },
147
+ _escape: function (e) {
148
+ if (e.keyCode === 27) {
149
+ if (this._latlngs.length) {
150
+ this._closePath();
151
+ } else {
152
+ this._enabled = true;
153
+ this._toggleMeasure();
154
+ }
155
+ }
156
+ },
157
+ _calculateBearing: function (start, end) {
158
+ const toRad = L.DomUtil.DEG_TO_RAD;
159
+ const toDeg = (this.options.angleUnit.factor / 2) / Math.PI;
160
+ let y = Math.sin((end.lng - start.lng) * toRad) * Math.cos(end.lat * toRad);
161
+ let x = Math.cos(start.lat * toRad) * Math.sin(end.lat * toRad) - Math.sin(start.lat * toRad) * Math.cos(end.lat * toRad) * Math.cos((end.lng - start.lng) * toRad);
162
+ return (Math.atan2(y, x) * toDeg + this.options.angleUnit.factor) % this.options.angleUnit.factor;
163
+ },
164
+ _closePath: function () {
165
+ if (this._tempLine) {
166
+ this._tempLine.remove();
167
+ this._tempLine = null;
168
+ }
169
+ if (this._tempPoint) {
170
+ this._tempPoint.remove();
171
+ this._tempLine = null;
172
+ }
173
+ if (this._latlngs.length <= 1) {
174
+ this._circles.remove();
175
+ }
176
+ this._enabled = false;
177
+ L.DomEvent.on(this._container, 'click', this._toggleMeasure, this);
178
+ this._toggleMeasure();
179
+ },
180
+ });
181
+ L.control.ruler = function (options) {
182
+ return new L.Control.Ruler(options);
183
183
  };
package/package.json CHANGED
@@ -1,17 +1,15 @@
1
1
  {
2
2
  "name": "@raruto/leaflet-elevation",
3
- "version": "2.6.0",
3
+ "version": "2.7.0",
4
4
  "description": "A Leaflet plugin that allows to add elevation profiles using d3js",
5
5
  "type": "module",
6
6
  "main": "dist/leaflet-elevation.min.js",
7
7
  "browser": "dist/leaflet-elevation.min.js",
8
8
  "module": "src/index.js",
9
9
  "scripts": {
10
- "test": "uvu . \"(examples|src)[\\\\/].*\\.spec\\.js$\"",
11
- "build": "rollup -c build/rollup.config.js",
12
- "watch": "rollup -c build/rollup.config.js --watch",
13
- "dev": "npm-run-all --print-label --parallel serve watch",
14
- "serve": "http-server",
10
+ "test": "node --test --test-concurrency=1 \"examples/*.spec.js\" \"src/*.spec.js\"",
11
+ "build": "node build/build.js",
12
+ "dev": "node build/dev.js",
15
13
  "version": "npm run build && git add -A"
16
14
  },
17
15
  "repository": {
@@ -50,20 +48,9 @@
50
48
  },
51
49
  "homepage": "https://github.com/Raruto/leaflet-elevation#readme",
52
50
  "devDependencies": {
53
- "@rollup/plugin-commonjs": "^24.1.0",
54
- "@rollup/plugin-node-resolve": "^15.0.2",
55
- "@rollup/plugin-terser": "^0.4.1",
56
- "http-server": "^14.1.1",
57
- "jsdom": "^21.1.1",
51
+ "esbuild": "^0.28.2",
58
52
  "leaflet": "^1.7.1",
59
- "npm-run-all": "^4.1.5",
60
- "playwright": "^1.32.3",
61
- "postcss": "^8.4.23",
62
- "postcss-copy": "^7.1.0",
63
- "postcss-import": "^15.1.0",
64
- "rollup": "^3.21.0",
65
- "rollup-plugin-postcss": "^4.0.2",
66
- "uvu": "^0.5.6"
53
+ "playwright": "^1.32.3"
67
54
  },
68
55
  "peerDependencies": {
69
56
  "@tmcw/togeojson": "5.6.2",
@@ -155,6 +155,12 @@ export var Chart = L.Control.Elevation.Chart = L.Class.extend({
155
155
  }
156
156
 
157
157
  const focus = (e) => {
158
+ const sourceEvent = e.sourceEvent || e;
159
+ // fixes: https://github.com/Raruto/leaflet-elevation/issues/311
160
+ if (!this.options.detached && sourceEvent.stopPropagation) {
161
+ sourceEvent.stopPropagation();
162
+ }
163
+
158
164
  if (this._data.length && (e.type != 'brush' /*|| e.sourceEvent*/)) {
159
165
  let rect = this._chart.panes.brush.select('.overlay').node();
160
166
  let coords = d3.pointers(e, rect)[0];
@@ -52,7 +52,9 @@ export var Marker = L.Class.extend({
52
52
  let point = this._map.latLngToLayerPoint(this._latlng);
53
53
  point = L.extend({}, props.item, this._map._rotate ? this._map.rotatedPointToMapPanePoint(point) : point);
54
54
 
55
- let yMax = (this.control._height() / props.yCoordMax * point[this.options.yAttr]);
55
+ // Keep the zero baseline unless the track extends below sea level.
56
+ let yMin = props.yCoordMin || 0;
57
+ let yMax = (this.control._height() / (props.yCoordMax - yMin) * (point[this.options.yAttr] - yMin));
56
58
 
57
59
  if (!isFinite(yMax) || isNaN(yMax)) yMax = 0;
58
60
 
@@ -1,43 +1,43 @@
1
- const _ = L.Control.Elevation.Utils;
2
-
3
- export var Summary = L.Class.extend({
4
- initialize(opts, control) {
5
- this.options = opts;
6
- this.control = control;
7
- this.labels = {};
8
-
9
- let summary = this._container = _.create("div", "elevation-summary " + (opts.summary ? opts.summary + "-summary" : ''));
10
- _.style(summary, 'max-width', opts.width ? opts.width + 'px' : '');
11
- },
12
-
13
- render() {
14
- return container => container.append(() => this._container);
15
- },
16
-
17
- reset() {
18
- this._container.innerHTML = '';
19
- },
20
-
21
- append(className, label, value) {
22
- this._container.innerHTML += `<span class="${className}"><span class="summarylabel">${label}</span><span class="summaryvalue">${value}</span></span>`;
23
- return this;
24
- },
25
-
26
- update() {
27
- Object
28
- .keys(this.labels)
29
- .sort((a, b) => this.labels[a].order - this.labels[b].order) // TODO: any performance issues?
30
- .forEach((i)=> {
31
- let value = typeof this.labels[i].value !== "function" ? this.labels[i].value : this.labels[i].value(this.control.track_info, this.labels[i].unit || '');
32
- this.append(i /*+ " order-" + this.labels[i].order*/, L._(this.labels[i].label), value, this.labels[i].order);
33
- });
34
- },
35
-
36
- _registerSummary(data) {
37
- for (let i in data) {
38
- data[i].order = data[i].order ?? 1000;
39
- this.labels[i] = data[i];
40
- }
41
- }
42
-
43
- });
1
+ const _ = L.Control.Elevation.Utils;
2
+
3
+ export var Summary = L.Class.extend({
4
+ initialize(opts, control) {
5
+ this.options = opts;
6
+ this.control = control;
7
+ this.labels = {};
8
+
9
+ let summary = this._container = _.create("div", "elevation-summary " + (opts.summary ? opts.summary + "-summary" : ''));
10
+ _.style(summary, 'max-width', opts.width ? opts.width + 'px' : '');
11
+ },
12
+
13
+ render() {
14
+ return container => container.append(() => this._container);
15
+ },
16
+
17
+ reset() {
18
+ this._container.innerHTML = '';
19
+ },
20
+
21
+ append(className, label, value) {
22
+ this._container.innerHTML += `<span class="${className}"><span class="summarylabel">${label}</span><span class="summaryvalue">${value}</span></span>`;
23
+ return this;
24
+ },
25
+
26
+ update() {
27
+ Object
28
+ .keys(this.labels)
29
+ .sort((a, b) => this.labels[a].order - this.labels[b].order) // TODO: any performance issues?
30
+ .forEach((i)=> {
31
+ let value = typeof this.labels[i].value !== "function" ? this.labels[i].value : this.labels[i].value(this.control.track_info, this.labels[i].unit || '');
32
+ this.append(i /*+ " order-" + this.labels[i].order*/, L._(this.labels[i].label), value, this.labels[i].order);
33
+ });
34
+ },
35
+
36
+ _registerSummary(data) {
37
+ for (let i in data) {
38
+ data[i].order = data[i].order ?? 1000;
39
+ this.labels[i] = data[i];
40
+ }
41
+ }
42
+
43
+ });
package/src/control.js CHANGED
@@ -71,6 +71,8 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
71
71
 
72
72
  this._data = [];
73
73
  this.track_info = {};
74
+ this._yCoordMin = 0;
75
+ this._yCoordMax = -Infinity;
74
76
 
75
77
  this._fireEvt("eledata_clear");
76
78
 
@@ -186,6 +188,7 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
186
188
  this._start = L.circleMarker([0,0], (opts.trkStart || Options.trkStart));
187
189
  this._end = L.circleMarker([0,0], (opts.trkEnd || Options.trkEnd));
188
190
  this._chartEnabled = true;
191
+ this._yCoordMin = 0;
189
192
  this._yCoordMax = -Infinity;
190
193
  this.track_info = {};
191
194
  // this.handlers = [];
@@ -362,6 +365,7 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
362
365
 
363
366
  this.fire("elepoint_added", { point: point, index: this._data.length - 1 });
364
367
 
368
+ if (this._yCoordMin > this._data[this._data.length - 1][this.options.yAttr]) this._yCoordMin = this._data[this._data.length - 1][this.options.yAttr];
365
369
  if (this._yCoordMax < this._data[this._data.length - 1][this.options.yAttr]) this._yCoordMax = this._data[this._data.length - 1][this.options.yAttr];
366
370
  });
367
371
 
@@ -1262,6 +1266,7 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
1262
1266
  this._marker.update({
1263
1267
  map : this._map,
1264
1268
  item : item,
1269
+ yCoordMin : this._yCoordMin,
1265
1270
  yCoordMax : this._yCoordMax || 0,
1266
1271
  options : this.options
1267
1272
  });