@raruto/leaflet-elevation 1.9.3 → 1.9.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/README.md +5 -4
- package/dist/leaflet-elevation.js +564 -410
- package/dist/leaflet-elevation.js.map +1 -1
- package/dist/leaflet-elevation.min.js +2 -2
- package/dist/leaflet-elevation.min.js.map +1 -1
- package/libs/leaflet-distance-marker.js +239 -80
- package/libs/leaflet-distance-marker.min.js +1 -1
- package/libs/leaflet-ruler.css +42 -0
- package/libs/leaflet-ruler.js +183 -0
- package/libs/leaflet-ruler.min.css +1 -0
- package/libs/leaflet-ruler.min.js +1 -0
- package/package.json +1 -1
- package/src/acceleration.js +56 -51
- package/src/altitude.js +78 -79
- package/src/chart.js +10 -0
- package/src/components.js +18 -11
- package/src/control.js +108 -45
- package/src/distance.js +31 -40
- package/src/index.js +1 -1
- package/src/options.js +9 -5
- package/src/slope.js +87 -71
- package/src/speed.js +57 -49
- package/src/summary.js +12 -1
- package/src/time.js +44 -42
package/src/control.js
CHANGED
|
@@ -17,7 +17,7 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
17
17
|
__TOGEOJSON: 'https://unpkg.com/@tmcw/togeojson@4.5.0/dist/togeojson.umd.js',
|
|
18
18
|
__LGEOMUTIL: 'https://unpkg.com/leaflet-geometryutil@0.9.3/src/leaflet.geometryutil.js',
|
|
19
19
|
__LALMOSTOVER: 'https://unpkg.com/leaflet-almostover@1.0.1/src/leaflet.almostover.js',
|
|
20
|
-
__LDISTANCEM: 'https://unpkg.com/@raruto/leaflet-elevation@1.9.
|
|
20
|
+
__LDISTANCEM: 'https://unpkg.com/@raruto/leaflet-elevation@1.9.6/libs/leaflet-distance-marker.min.js',
|
|
21
21
|
|
|
22
22
|
/*
|
|
23
23
|
* Add data to the diagram either from GPX or GeoJSON and update the axis domain and data
|
|
@@ -89,6 +89,22 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
89
89
|
}
|
|
90
90
|
},
|
|
91
91
|
|
|
92
|
+
/**
|
|
93
|
+
* TODO: Create a base class to handle custom data attributes (heart rate, cadence, temperature, ...)
|
|
94
|
+
*
|
|
95
|
+
* @link https://leafletjs.com/examples/extending/extending-3-controls.html#handlers
|
|
96
|
+
*/
|
|
97
|
+
// addHandler: function (name, HandlerClass) {
|
|
98
|
+
// if (HandlerClass) {
|
|
99
|
+
// let handler = this[name] = new HandlerClass(this);
|
|
100
|
+
// this.handlers.push(handler);
|
|
101
|
+
// if (this.options[name]) {
|
|
102
|
+
// handler.enable();
|
|
103
|
+
// }
|
|
104
|
+
// }
|
|
105
|
+
// return this;
|
|
106
|
+
// },
|
|
107
|
+
|
|
92
108
|
/**
|
|
93
109
|
* Disable chart brushing.
|
|
94
110
|
*/
|
|
@@ -133,7 +149,7 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
133
149
|
},
|
|
134
150
|
|
|
135
151
|
/**
|
|
136
|
-
* Get default zoom level
|
|
152
|
+
* Get default zoom level (followMarker: true).
|
|
137
153
|
*/
|
|
138
154
|
getZFollow: function() {
|
|
139
155
|
return this.options.zFollow;
|
|
@@ -156,6 +172,7 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
156
172
|
this._markedSegments = L.polyline([]);
|
|
157
173
|
this._chartEnabled = true,
|
|
158
174
|
this.track_info = {};
|
|
175
|
+
this.handlers = [];
|
|
159
176
|
|
|
160
177
|
L.setOptions(this, options);
|
|
161
178
|
|
|
@@ -163,7 +180,7 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
163
180
|
if (this.options.legend) this.options.margins.bottom += 30;
|
|
164
181
|
if (this.options.theme) this.options.polylineSegments.className += ' ' + this.options.theme;
|
|
165
182
|
if (this.options.wptIcons === true) this.options.wptIcons = Options.wptIcons;
|
|
166
|
-
if (this.options.distanceMarkers === true) this.options.distanceMarkers =
|
|
183
|
+
if (this.options.distanceMarkers === true) this.options.distanceMarkers = Options.distanceMarkers;
|
|
167
184
|
|
|
168
185
|
this._markedSegments.setStyle(this.options.polylineSegments);
|
|
169
186
|
|
|
@@ -208,7 +225,7 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
208
225
|
},
|
|
209
226
|
|
|
210
227
|
/**
|
|
211
|
-
* Load elevation data (GPX, GeoJSON or
|
|
228
|
+
* Load elevation data (GPX, GeoJSON, KML or TCX).
|
|
212
229
|
*/
|
|
213
230
|
load: function(data) {
|
|
214
231
|
this._parseFromString(data).then( geojson => geojson ? this._loadLayer(geojson) : this._loadFile(data));
|
|
@@ -283,7 +300,7 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
283
300
|
},
|
|
284
301
|
|
|
285
302
|
/**
|
|
286
|
-
* Set default zoom level
|
|
303
|
+
* Set default zoom level (followMarker: true).
|
|
287
304
|
*/
|
|
288
305
|
setZFollow: function(zoom) {
|
|
289
306
|
this.options.zFollow = zoom;
|
|
@@ -343,20 +360,10 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
343
360
|
// Inspired by L.GPX layer properties
|
|
344
361
|
point.meta = point.meta ?? { time: null, ele: null, hr: null, cad: null, atemp: null };
|
|
345
362
|
|
|
346
|
-
// "alt" property is generated inside "leaflet"
|
|
347
|
-
if ("alt" in point) point.meta.ele = point.alt;
|
|
348
|
-
|
|
349
363
|
// "coordinateProperties" property is generated inside "@tmcw/toGeoJSON"
|
|
350
364
|
let props = (properties && properties.coordinateProperties) || properties;
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
else if("times" in props) point.meta.time = new Date(Date.parse(props.times[i]));
|
|
354
|
-
else if("time" in props) point.meta.time = new Date(Date.parse((typeof props.time === 'object' ? props.time[i] : props.time)));
|
|
355
|
-
if ("heartRates" in props) point.meta.hr = parseInt(props.heartRates[i]);
|
|
356
|
-
else if("heartRate" in props) point.meta.hr = parseInt((typeof props.heartRate === 'object' ? props.heartRate[i] : props.heartRate));
|
|
357
|
-
else if("heart" in props) point.meta.hr = parseInt((typeof props.heart === 'object' ? props.heart[i] : props.heart));
|
|
358
|
-
// TODO: ask to "@tmcw/toGeoJSON" for "cadence" and "temperature" implementation
|
|
359
|
-
}
|
|
365
|
+
|
|
366
|
+
this.fire("elepoint_init", { point: point, props: props, id: i });
|
|
360
367
|
|
|
361
368
|
this._addPoint(
|
|
362
369
|
point.lat ?? point[1],
|
|
@@ -364,10 +371,10 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
364
371
|
point.alt ?? point.meta.ele ?? point[2]
|
|
365
372
|
);
|
|
366
373
|
|
|
367
|
-
this.
|
|
374
|
+
this.fire("elepoint_added", { point: point, index: this._data.length - 1 });
|
|
368
375
|
});
|
|
369
376
|
|
|
370
|
-
this.
|
|
377
|
+
this.fire("eletrack_added", { coords: coords, index: this._data.length - 1 });
|
|
371
378
|
},
|
|
372
379
|
|
|
373
380
|
/*
|
|
@@ -385,7 +392,7 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
385
392
|
latlng: L.latLng(x, y, z)
|
|
386
393
|
});
|
|
387
394
|
|
|
388
|
-
this.
|
|
395
|
+
this.fire("eledata_updated", { index: this._data.length - 1 });
|
|
389
396
|
},
|
|
390
397
|
|
|
391
398
|
_addLayer: function(layer) {
|
|
@@ -572,7 +579,7 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
572
579
|
},
|
|
573
580
|
|
|
574
581
|
/**
|
|
575
|
-
* Generate "svg" chart DOM element.
|
|
582
|
+
* Generate "svg" chart (DOM element).
|
|
576
583
|
*/
|
|
577
584
|
_initChart: function(container) {
|
|
578
585
|
let opts = this.options;
|
|
@@ -602,7 +609,7 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
602
609
|
|
|
603
610
|
chart
|
|
604
611
|
.on('reset_drag', this._hideMarker, this)
|
|
605
|
-
.on('mouse_enter', this.
|
|
612
|
+
.on('mouse_enter', this._mouseenterHandler, this)
|
|
606
613
|
.on('dragged', this._dragendHandler, this)
|
|
607
614
|
.on('mouse_move', this._mousemoveHandler, this)
|
|
608
615
|
.on('mouse_out', this._mouseoutHandler, this)
|
|
@@ -612,10 +619,11 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
612
619
|
.on('margins_updated',this._resizeChart, this);
|
|
613
620
|
|
|
614
621
|
|
|
615
|
-
this.
|
|
616
|
-
|
|
622
|
+
this.fire("elechart_axis");
|
|
623
|
+
|
|
624
|
+
if (this.options.legend) this.fire("elechart_legend");
|
|
617
625
|
|
|
618
|
-
this.
|
|
626
|
+
this.fire("elechart_init");
|
|
619
627
|
},
|
|
620
628
|
|
|
621
629
|
_initLayer: function() {
|
|
@@ -641,7 +649,7 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
641
649
|
this._renderer = L.svg({ pane: "elevationPane" }).addTo(this._map); // default leaflet svg renderer
|
|
642
650
|
this._marker = new Marker(this.options);
|
|
643
651
|
|
|
644
|
-
this.
|
|
652
|
+
this.fire("elechart_marker");
|
|
645
653
|
},
|
|
646
654
|
|
|
647
655
|
/**
|
|
@@ -772,7 +780,14 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
772
780
|
this._hideMarker();
|
|
773
781
|
this.fitBounds(L.latLngBounds([e.dragstart.latlng, e.dragend.latlng]));
|
|
774
782
|
|
|
775
|
-
this.
|
|
783
|
+
this.fire("elechart_dragged");
|
|
784
|
+
},
|
|
785
|
+
|
|
786
|
+
/**
|
|
787
|
+
* Trigger mouseenter event
|
|
788
|
+
*/
|
|
789
|
+
_mouseenterHandler: function(e) {
|
|
790
|
+
this.fire('elechart_enter');
|
|
776
791
|
},
|
|
777
792
|
|
|
778
793
|
/*
|
|
@@ -796,8 +811,8 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
796
811
|
_.addClass(this._map.getContainer(), 'elechart-hover');
|
|
797
812
|
}
|
|
798
813
|
|
|
799
|
-
this.
|
|
800
|
-
this.
|
|
814
|
+
this.fire("elechart_change", { data: item, xCoord: xCoord });
|
|
815
|
+
this.fire("elechart_hover", { data: item, xCoord: xCoord });
|
|
801
816
|
}
|
|
802
817
|
},
|
|
803
818
|
|
|
@@ -817,7 +832,7 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
817
832
|
|
|
818
833
|
this._updateMarker(item);
|
|
819
834
|
|
|
820
|
-
this.
|
|
835
|
+
this.fire("elechart_change", { data: item, xCoord: xCoord });
|
|
821
836
|
}
|
|
822
837
|
},
|
|
823
838
|
|
|
@@ -834,7 +849,7 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
834
849
|
_.removeClass(this._map.getContainer(), 'elechart-hover');
|
|
835
850
|
}
|
|
836
851
|
|
|
837
|
-
this.
|
|
852
|
+
this.fire("elechart_leave");
|
|
838
853
|
},
|
|
839
854
|
|
|
840
855
|
/**
|
|
@@ -919,13 +934,6 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
919
934
|
return geojson.features.filter(feauture => feauture.geometry.type != "MultiLineString");
|
|
920
935
|
},
|
|
921
936
|
|
|
922
|
-
/**
|
|
923
|
-
* Add a point of interest over the diagram
|
|
924
|
-
*/
|
|
925
|
-
_registerCheckPoint: function(props) {
|
|
926
|
-
this.on("elechart_updated", () => this._chart._registerCheckPoint(props));
|
|
927
|
-
},
|
|
928
|
-
|
|
929
937
|
/**
|
|
930
938
|
* Add chart profile to diagram
|
|
931
939
|
*/
|
|
@@ -947,6 +955,60 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
947
955
|
this.on("elechart_axis", () => this._chart._registerAxisScale(props));
|
|
948
956
|
},
|
|
949
957
|
|
|
958
|
+
/**
|
|
959
|
+
* Add a point of interest over the diagram
|
|
960
|
+
*/
|
|
961
|
+
_registerCheckPoint: function(props) {
|
|
962
|
+
this.on("elechart_updated", () => this._chart._registerCheckPoint(props));
|
|
963
|
+
},
|
|
964
|
+
|
|
965
|
+
|
|
966
|
+
/**
|
|
967
|
+
* Base handler for iterative track statistics (dist, time, z, slope, speed, acceleration, ...)
|
|
968
|
+
*/
|
|
969
|
+
_registerDataAttribute: function(props) {
|
|
970
|
+
// save here a reference to last used point
|
|
971
|
+
let lastValid = null;
|
|
972
|
+
|
|
973
|
+
// parse of "coordinateProperties" for later usage
|
|
974
|
+
if (props.init) {
|
|
975
|
+
this.on("elepoint_init", (e) => props.init.call(this, e));
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
// iteration
|
|
979
|
+
this.on("elepoint_added", (e) => {
|
|
980
|
+
|
|
981
|
+
// check and fix missing data on last added point
|
|
982
|
+
if (props.skipNull === false) {
|
|
983
|
+
let curr = this._data[e.index][props.name];
|
|
984
|
+
if(e.index > 0) {
|
|
985
|
+
let prev = this._data[e.index - 1][props.name];
|
|
986
|
+
if (isNaN(prev)) {
|
|
987
|
+
if (!isNaN(lastValid) && !isNaN(curr)) {
|
|
988
|
+
prev = (lastValid + curr) / 2;
|
|
989
|
+
} else if (!isNaN(lastValid)) {
|
|
990
|
+
prev = lastValid;
|
|
991
|
+
} else if (!isNaN(curr)) {
|
|
992
|
+
prev = curr;
|
|
993
|
+
}
|
|
994
|
+
if (!isNaN(prev)) return this._data.splice(e.index - 1, 1);
|
|
995
|
+
this._data[e.index - 1][props.name] = prev;
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
// update reference to last used point (ie. if it has data)
|
|
999
|
+
if (!isNaN(curr)) {
|
|
1000
|
+
lastValid = curr;
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
// retrieve point value
|
|
1005
|
+
this._data[e.index][props.name] = props.fetch.call(this, e.index, e.point);
|
|
1006
|
+
|
|
1007
|
+
// update here some mixins (eg. "track_info", value validators, ...)
|
|
1008
|
+
if(props.update) this._data[e.index][props.name] = props.update.call(this, this._data[e.index][props.name], e.index, e.point)
|
|
1009
|
+
});
|
|
1010
|
+
},
|
|
1011
|
+
|
|
950
1012
|
/**
|
|
951
1013
|
* Add chart or marker tooltip info
|
|
952
1014
|
*/
|
|
@@ -1030,7 +1092,7 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
1030
1092
|
},
|
|
1031
1093
|
|
|
1032
1094
|
/**
|
|
1033
|
-
* Collapse or Expand
|
|
1095
|
+
* Collapse or Expand chart control.
|
|
1034
1096
|
*/
|
|
1035
1097
|
_toggle: function() {
|
|
1036
1098
|
if (_.hasClass(this._container, "elevation-expanded"))
|
|
@@ -1040,7 +1102,7 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
1040
1102
|
},
|
|
1041
1103
|
|
|
1042
1104
|
/**
|
|
1043
|
-
*
|
|
1105
|
+
* Update map center and zoom (followMarker: true)
|
|
1044
1106
|
*/
|
|
1045
1107
|
_setMapView: function(item) {
|
|
1046
1108
|
if (!this.options.followMarker || !this._map) return;
|
|
@@ -1080,15 +1142,15 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
1080
1142
|
_updateChart: function() {
|
|
1081
1143
|
if (/*!this._data.length ||*/ !this._chart || !this._container) return;
|
|
1082
1144
|
|
|
1083
|
-
this.
|
|
1084
|
-
this.
|
|
1145
|
+
this.fire("elechart_axis");
|
|
1146
|
+
this.fire("elechart_area");
|
|
1085
1147
|
|
|
1086
1148
|
this._chart.update({ data: this._data, options: this.options });
|
|
1087
1149
|
|
|
1088
1150
|
this._x = this._chart._x;
|
|
1089
1151
|
this._y = this._chart._y;
|
|
1090
1152
|
|
|
1091
|
-
this.
|
|
1153
|
+
this.fire('elechart_updated');
|
|
1092
1154
|
},
|
|
1093
1155
|
|
|
1094
1156
|
/*
|
|
@@ -1131,7 +1193,8 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
1131
1193
|
this._summary.reset();
|
|
1132
1194
|
|
|
1133
1195
|
if (this.options.summary) {
|
|
1134
|
-
this.
|
|
1196
|
+
this.fire("elechart_summary");
|
|
1197
|
+
this._summary.update();
|
|
1135
1198
|
}
|
|
1136
1199
|
if (this.options.downloadLink && this._downloadURL) { // TODO: generate dynamically file content instead of using static file urls.
|
|
1137
1200
|
this._summary._container.innerHTML += '<span class="download"><a href="#">' + L._('Download') + '</a></span>'
|
|
@@ -1143,7 +1206,7 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
1143
1206
|
} else if (this.options.downloadLink == 'link' || this.options.downloadLink === true) {
|
|
1144
1207
|
event.confirm();
|
|
1145
1208
|
}
|
|
1146
|
-
this.
|
|
1209
|
+
this.fire('eletrack_download', event);
|
|
1147
1210
|
};
|
|
1148
1211
|
};
|
|
1149
1212
|
},
|
package/src/distance.js
CHANGED
|
@@ -16,62 +16,53 @@ Elevation.addInitHook(function() {
|
|
|
16
16
|
distance.label = opts.xLabel;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
this.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
track.distance = dist;
|
|
34
|
-
|
|
35
|
-
data[i].dist = dist;
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
this.on("elechart_axis", function() {
|
|
39
|
-
|
|
40
|
-
this._chart._registerAxisGrid({
|
|
41
|
-
axis : "x",
|
|
42
|
-
position : "bottom",
|
|
43
|
-
scale : this._chart._x,
|
|
44
|
-
});
|
|
45
|
-
|
|
19
|
+
this._registerDataAttribute({
|
|
20
|
+
name: 'dist',
|
|
21
|
+
init: () => {
|
|
22
|
+
// this.track_info.distance = 0;
|
|
23
|
+
},
|
|
24
|
+
fetch: (i) => {
|
|
25
|
+
let delta = this._data[i].latlng.distanceTo(this._data[i > 0 ? i - 1 : i].latlng) * opts.distanceFactor;
|
|
26
|
+
return Math.round(delta / 1000 * 100000) / 100000; // handles floating points calc
|
|
27
|
+
},
|
|
28
|
+
update: (distance) => {
|
|
29
|
+
this.track_info.distance = this.track_info.distance || 0;
|
|
30
|
+
this.track_info.distance += distance;
|
|
31
|
+
return this.track_info.distance;
|
|
32
|
+
}
|
|
46
33
|
});
|
|
47
34
|
|
|
48
35
|
if (this.options.distance != "summary") {
|
|
49
36
|
|
|
50
|
-
this.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
labelX : () => this._width() + 6,
|
|
59
|
-
name : "distance",
|
|
60
|
-
});
|
|
61
|
-
|
|
37
|
+
this._registerAxisScale({
|
|
38
|
+
axis : "x",
|
|
39
|
+
position: "bottom",
|
|
40
|
+
scale : "x", // this._chart._x,
|
|
41
|
+
label : distance.label,
|
|
42
|
+
labelY : 25,
|
|
43
|
+
labelX : () => this._width() + 6,
|
|
44
|
+
name : "distance",
|
|
62
45
|
});
|
|
63
46
|
|
|
64
47
|
}
|
|
65
48
|
|
|
49
|
+
this._registerAxisGrid({
|
|
50
|
+
axis : "x",
|
|
51
|
+
position : "bottom",
|
|
52
|
+
scale : "x" // this._chart._x,
|
|
53
|
+
});
|
|
54
|
+
|
|
66
55
|
this._registerTooltip({
|
|
67
56
|
name: 'x',
|
|
68
57
|
chart: (item) => L._("x: ") + d3.format("." + opts.decimalsX + "f")(item[opts.xAttr]) + " " + distance.label,
|
|
58
|
+
order: 20
|
|
69
59
|
});
|
|
70
60
|
|
|
71
61
|
this._registerSummary({
|
|
72
62
|
"totlen" : {
|
|
73
63
|
label: "Total Length: ",
|
|
74
|
-
value: (track) => (track.distance || 0).toFixed(2) + ' ' + distance.label
|
|
64
|
+
value: (track) => (track.distance || 0).toFixed(2) + ' ' + distance.label,
|
|
65
|
+
order: 10
|
|
75
66
|
}
|
|
76
67
|
});
|
|
77
68
|
|
package/src/index.js
CHANGED
|
@@ -39,9 +39,9 @@ import * as _ from './utils';
|
|
|
39
39
|
import * as D3 from './components';
|
|
40
40
|
import { Chart } from './chart';
|
|
41
41
|
import { Elevation } from './control';
|
|
42
|
-
import './altitude';
|
|
43
42
|
import './distance';
|
|
44
43
|
import './time';
|
|
44
|
+
import './altitude';
|
|
45
45
|
import './slope';
|
|
46
46
|
import './speed';
|
|
47
47
|
import './acceleration';
|
package/src/options.js
CHANGED
|
@@ -9,7 +9,11 @@ export var Options = {
|
|
|
9
9
|
collapsed: false,
|
|
10
10
|
detached: true,
|
|
11
11
|
distance: true,
|
|
12
|
-
distanceMarkers:
|
|
12
|
+
distanceMarkers: {
|
|
13
|
+
lazy: true,
|
|
14
|
+
distance: true,
|
|
15
|
+
direction: true
|
|
16
|
+
},
|
|
13
17
|
decimalsX: 2,
|
|
14
18
|
decimalsY: 0,
|
|
15
19
|
dragging: !L.Browser.mobile,
|
|
@@ -55,15 +59,15 @@ export var Options = {
|
|
|
55
59
|
theme: "lightblue-theme",
|
|
56
60
|
summary: 'inline',
|
|
57
61
|
slope: false,
|
|
62
|
+
slopeDeltaMax: undefined,
|
|
63
|
+
slopeRange: undefined,
|
|
58
64
|
speed: false,
|
|
59
|
-
|
|
65
|
+
speedDeltaMax: undefined,
|
|
66
|
+
speedRange: undefined,
|
|
60
67
|
time: false,
|
|
61
68
|
timeFactor: 3600,
|
|
62
69
|
timeFormat: false,
|
|
63
70
|
timestamps: false,
|
|
64
|
-
sDeltaMax: undefined,
|
|
65
|
-
sInterpolation: "curveStepAfter",
|
|
66
|
-
sRange: undefined,
|
|
67
71
|
width: 600,
|
|
68
72
|
waypoints: true,
|
|
69
73
|
wptIcons: {
|
package/src/slope.js
CHANGED
|
@@ -12,100 +12,116 @@ Elevation.addInitHook(function() {
|
|
|
12
12
|
|
|
13
13
|
slope.label = opts.slopeLabel || '%';
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
let z = data[i].z;
|
|
49
|
-
let delta = (data[i].dist - data[i > 0 ? i - 1 : i].dist) * 1000;
|
|
50
|
-
|
|
51
|
-
// Slope / Gain
|
|
52
|
-
let track = this.track_info;
|
|
53
|
-
let tAsc = track.ascent || 0; // Total Ascent
|
|
54
|
-
let tDes = track.descent || 0; // Total Descent
|
|
55
|
-
let sMax = track.slope_max || 0; // Slope Max
|
|
56
|
-
let sMin = track.slope_min || 0; // Slope Min
|
|
57
|
-
let slope = 0;
|
|
58
|
-
|
|
59
|
-
if (!isNaN(z)) {
|
|
60
|
-
let deltaZ = i > 0 ? z - data[i - 1].z : 0;
|
|
61
|
-
if (deltaZ > 0) tAsc += deltaZ;
|
|
62
|
-
else if (deltaZ < 0) tDes -= deltaZ;
|
|
63
|
-
// slope in % = ( height / length ) * 100
|
|
64
|
-
if (delta !== 0) slope = (deltaZ / delta) * 100;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Try to smooth "crazy" slope values.
|
|
68
|
-
if (this.options.sDeltaMax) {
|
|
69
|
-
let deltaS = i > 0 ? slope - data[i - 1].slope : 0;
|
|
70
|
-
let maxDeltaS = this.options.sDeltaMax;
|
|
71
|
-
if (Math.abs(deltaS) > maxDeltaS) {
|
|
72
|
-
slope = data[i - 1].slope + maxDeltaS * Math.sign(deltaS);
|
|
15
|
+
this._registerDataAttribute({
|
|
16
|
+
name: 'slope',
|
|
17
|
+
// init: () => {
|
|
18
|
+
// // this.track_info.ascent = 0; // Total Ascent
|
|
19
|
+
// // this.track_info.descent = 0; // Total Descent
|
|
20
|
+
// // this.track_info.slope_max = -Infinity; // Slope Max
|
|
21
|
+
// // this.track_info.slope_min = +Infinity; // Slope Min
|
|
22
|
+
// // this.track_info.slope_avg = 0; // Acceleration Avg
|
|
23
|
+
// },
|
|
24
|
+
fetch: (i) => {
|
|
25
|
+
let data = this._data;
|
|
26
|
+
let dx = (data[i].dist - data[i > 0 ? i - 1 : i].dist) * 1000;
|
|
27
|
+
let dz = data[i].z - data[i > 0 ? i - 1 : i].z;
|
|
28
|
+
return (!isNaN(dz) && dx !== 0) ? (dz / dx) * 100 : 0; // slope in % = ( height / length ) * 100;
|
|
29
|
+
},
|
|
30
|
+
update: (slope, i) => {
|
|
31
|
+
this.track_info.ascent = this.track_info.ascent || 0; // Total Ascent
|
|
32
|
+
this.track_info.descent = this.track_info.descent || 0; // Total Descent
|
|
33
|
+
this.track_info.slope_max = this.track_info.slope_max || -Infinity; // Slope Max
|
|
34
|
+
this.track_info.slope_min = this.track_info.slope_min || +Infinity; // Slope Min
|
|
35
|
+
this.track_info.slope_avg = this.track_info.slope_avg || 0; // Acceleration Avg
|
|
36
|
+
|
|
37
|
+
let track = this.track_info;
|
|
38
|
+
let data = this._data;
|
|
39
|
+
let dz = data[i].z - data[i > 0 ? i - 1 : i].z;
|
|
40
|
+
|
|
41
|
+
// Try to smooth "crazy" acceleration values.
|
|
42
|
+
if (this.options.slopeDeltaMax) {
|
|
43
|
+
let delta = slop - data[i > 0 ? i - 1 : i].slope;
|
|
44
|
+
let deltaMax = this.options.slopeDeltaMax;
|
|
45
|
+
if (Math.abs(delta) > deltaMax) {
|
|
46
|
+
slope = data[i - 1].slope + deltaMax * Math.sign(delta);
|
|
47
|
+
}
|
|
73
48
|
}
|
|
74
|
-
}
|
|
75
49
|
|
|
76
|
-
|
|
77
|
-
|
|
50
|
+
// Range of acceptable slope values.
|
|
51
|
+
slope = _.clamp(slope, this.options.slopeRange);
|
|
52
|
+
|
|
53
|
+
if (dz > 0) this.track_info.ascent += dz;
|
|
54
|
+
else if (dz < 0) this.track_info.descent -= dz;
|
|
55
|
+
|
|
56
|
+
if (slope > track.slope_max) track.slope_max = slope;
|
|
57
|
+
if (slope < track.slope_min) track.slope_min = slope;
|
|
78
58
|
|
|
79
|
-
|
|
80
|
-
track.descent = tDes;
|
|
81
|
-
track.slope_max = slope > sMax ? slope : sMax;
|
|
82
|
-
track.slope_min = slope < sMin ? slope : sMin;
|
|
59
|
+
track.slope_avg = (slope + track.slope_avg) / 2.0;
|
|
83
60
|
|
|
84
|
-
|
|
61
|
+
return L.Util.formatNum(slope, 2);;
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
this._registerAxisScale({
|
|
66
|
+
axis : "y",
|
|
67
|
+
position : "right",
|
|
68
|
+
scale : {
|
|
69
|
+
min : -1,
|
|
70
|
+
max : +1,
|
|
71
|
+
},
|
|
72
|
+
tickPadding: 16,
|
|
73
|
+
label : slope.label,
|
|
74
|
+
labelX : 25,
|
|
75
|
+
labelY : -8,
|
|
76
|
+
name : 'slope',
|
|
77
|
+
visbile : this.options.slope != "summary"
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
this._registerAreaPath({
|
|
81
|
+
name : 'slope',
|
|
82
|
+
label : 'Slope',
|
|
83
|
+
yAttr : 'slope',
|
|
84
|
+
scaleX : 'distance',
|
|
85
|
+
scaleY : 'slope',
|
|
86
|
+
color : '#F00',
|
|
87
|
+
strokeColor : '#000',
|
|
88
|
+
strokeOpacity: "0.5",
|
|
89
|
+
fillOpacity : "0.25",
|
|
90
|
+
visbile : this.options.slope != "summary"
|
|
85
91
|
});
|
|
86
92
|
|
|
87
93
|
this._registerTooltip({
|
|
88
94
|
name: 'slope',
|
|
89
95
|
chart: (item) => L._("m: ") + item.slope + slope.label,
|
|
90
|
-
marker: (item) => Math.round(item.slope) + slope.label
|
|
96
|
+
marker: (item) => Math.round(item.slope) + slope.label,
|
|
97
|
+
order: 40,
|
|
91
98
|
});
|
|
92
99
|
|
|
93
100
|
this._registerSummary({
|
|
94
101
|
"ascent" : {
|
|
95
102
|
label: "Total Ascent: ",
|
|
96
|
-
value: (track) => Math.round(track.ascent || 0) + ' ' + (this.options.imperial ? 'ft' : 'm')
|
|
103
|
+
value: (track) => Math.round(track.ascent || 0) + ' ' + (this.options.imperial ? 'ft' : 'm'),
|
|
104
|
+
order: 40
|
|
97
105
|
},
|
|
98
106
|
"descent" : {
|
|
99
107
|
label: "Total Descent: ",
|
|
100
|
-
value: (track) => Math.round(track.descent || 0) + ' ' + (this.options.imperial ? 'ft' : 'm')
|
|
108
|
+
value: (track) => Math.round(track.descent || 0) + ' ' + (this.options.imperial ? 'ft' : 'm'),
|
|
109
|
+
order: 40
|
|
101
110
|
},
|
|
102
111
|
"minslope": {
|
|
103
112
|
label: "Min Slope: ",
|
|
104
|
-
value: (track) => Math.round(track.slope_min || 0) + ' ' + slope.label
|
|
113
|
+
value: (track) => Math.round(track.slope_min || 0) + ' ' + slope.label,
|
|
114
|
+
order: 40
|
|
105
115
|
},
|
|
106
116
|
"maxslope": {
|
|
107
117
|
label: "Max Slope: ",
|
|
108
|
-
value: (track) => Math.round(track.slope_max || 0) + ' ' + slope.label
|
|
118
|
+
value: (track) => Math.round(track.slope_max || 0) + ' ' + slope.label,
|
|
119
|
+
order: 40
|
|
120
|
+
},
|
|
121
|
+
"avgslope": {
|
|
122
|
+
label: "Avg Slope: ",
|
|
123
|
+
value: (track) => Math.round(track.slope_avg || 0) + ' ' + slope.label,
|
|
124
|
+
order: 40
|
|
109
125
|
}
|
|
110
126
|
});
|
|
111
127
|
|