@raruto/leaflet-elevation 1.9.4 → 2.0.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.
Files changed (45) hide show
  1. package/README.md +8 -7
  2. package/dist/leaflet-elevation.css +51 -161
  3. package/dist/leaflet-elevation.js +1622 -3767
  4. package/dist/leaflet-elevation.js.map +1 -1
  5. package/dist/leaflet-elevation.min.css +1 -1
  6. package/dist/leaflet-elevation.min.js +1 -3
  7. package/dist/leaflet-elevation.min.js.map +1 -1
  8. package/images/checkered.png +0 -0
  9. package/libs/leaflet-distance-marker.js +17 -18
  10. package/libs/leaflet-distance-marker.min.js +1 -1
  11. package/libs/leaflet-gpxgroup.js +2 -2
  12. package/libs/leaflet-ruler.css +42 -0
  13. package/libs/leaflet-ruler.js +183 -0
  14. package/libs/leaflet-ruler.min.css +1 -0
  15. package/libs/leaflet-ruler.min.js +1 -0
  16. package/package.json +9 -11
  17. package/src/chart.js +156 -143
  18. package/src/components.js +55 -76
  19. package/src/control.js +503 -345
  20. package/src/handlers/acceleration.js +64 -0
  21. package/src/handlers/acceleration.min.js +1 -0
  22. package/src/handlers/altitude.js +76 -0
  23. package/src/handlers/altitude.min.js +1 -0
  24. package/src/handlers/cadence.js +54 -0
  25. package/src/handlers/distance.js +45 -0
  26. package/src/handlers/distance.min.js +1 -0
  27. package/src/handlers/heart.js +53 -0
  28. package/src/handlers/slope.js +79 -0
  29. package/src/handlers/slope.min.js +1 -0
  30. package/src/handlers/speed.js +66 -0
  31. package/src/handlers/speed.min.js +1 -0
  32. package/src/handlers/time.js +103 -0
  33. package/src/handlers/time.min.js +1 -0
  34. package/src/index.css +51 -161
  35. package/src/index.js +0 -24
  36. package/src/marker.js +11 -14
  37. package/src/options.js +20 -28
  38. package/src/summary.js +14 -4
  39. package/src/utils.js +74 -102
  40. package/src/acceleration.js +0 -108
  41. package/src/altitude.js +0 -120
  42. package/src/distance.js +0 -78
  43. package/src/slope.js +0 -113
  44. package/src/speed.js +0 -110
  45. package/src/time.js +0 -124
package/src/utils.js CHANGED
@@ -1,10 +1,23 @@
1
+ /**
2
+ * TODO: exget computed styles of theese values from actual "CSS vars"
3
+ **/
4
+ export const Colors = {
5
+ 'lightblue': { area: '#3366CC', alpha: 0.45, stroke: '#3366CC' },
6
+ 'magenta' : { area: '#FF005E' },
7
+ 'yellow' : { area: '#FF0' },
8
+ 'purple' : { area: '#732C7B' },
9
+ 'steelblue': { area: '#4682B4' },
10
+ 'red' : { area: '#F00' },
11
+ 'lime' : { area: '#9CC222', line: '#566B13' }
12
+ };
13
+
1
14
  const SEC = 1000;
2
15
  const MIN = SEC * 60;
3
16
  const HOUR = MIN * 60;
4
17
  const DAY = HOUR * 24;
5
18
 
6
19
  /**
7
- * Convert a duration time (millis) to a human readable string (%Dd %H:%M'%S")
20
+ * Convert a time (millis) to a human readable duration string (%Dd %H:%M'%S")
8
21
  */
9
22
  export function formatTime(t) {
10
23
  let d = Math.floor(t / DAY);
@@ -17,6 +30,20 @@ export function formatTime(t) {
17
30
  return (d ? d + "d " : '') + h.toString().padStart(2, 0) + ':' + m.toString().padStart(2, 0) + "'" + s.toString().padStart(2, 0) + '"';
18
31
  }
19
32
 
33
+ /**
34
+ * Convert a time (millis) to human readable date string (dd-mm-yyyy hh:mm:ss)
35
+ */
36
+ export function formatDate(format) {
37
+ if (!format) {
38
+ return (time) => (new Date(time)).toLocaleString().replaceAll('/', '-').replaceAll(',', ' ');
39
+ } else if (format == 'time') {
40
+ return (time) => (new Date(time)).toLocaleTimeString();
41
+ } else if (format == 'date') {
42
+ return (time) => (new Date(time)).toLocaleDateString();
43
+ }
44
+ return (time) => format(time);
45
+ }
46
+
20
47
  /**
21
48
  * Generate download data event.
22
49
  */
@@ -28,23 +55,6 @@ export function formatTime(t) {
28
55
  b.removeChild(a);
29
56
  }
30
57
 
31
- /**
32
- * Async JS script download.
33
- */
34
- export function lazyLoader(url, skip, loader) {
35
- if (skip === false) {
36
- return Promise.resolve();
37
- }
38
- if (loader instanceof Promise) {
39
- return loader;
40
- }
41
- return new Promise((resolve, reject) => {
42
- let tag = document.createElement("script");
43
- tag.addEventListener('load', resolve, { once: true });
44
- tag.src = url;
45
- document.head.appendChild(tag);
46
- });
47
- }
48
58
 
49
59
  /**
50
60
  * Convert SVG Path into Path2D and then update canvas
@@ -75,113 +85,75 @@ export function lazyLoader(url, skip, loader) {
75
85
  }
76
86
 
77
87
  /**
78
- * Limit a number between min / max values
79
- */
80
- export function clamp(val, range) {
81
- if (range) return val < range[0] ? range[0] : val > range[1] ? range[1] : val;
82
- return val;
83
- }
84
-
85
- /**
86
- * A little bit safier than L.DomUtil.addClass
88
+ * Loop and extract GPX Extensions handled by "@tmcw/toGeoJSON" (eg. "coordinateProperties" > "times")
87
89
  */
88
- export function addClass(targetNode, className) {
89
- if (targetNode) className.split(" ").every(s => s && L.DomUtil.addClass(targetNode, s));
90
- }
91
-
92
- /**
93
- * A little bit safier than L.DomUtil.removeClass()
94
- */
95
- export function removeClass(targetNode, className) {
96
- if (targetNode) className.split(" ").every(s => s && L.DomUtil.removeClass(targetNode, s));
97
- }
98
-
99
- export function toggleClass(targetNode, className, conditional) {
100
- return (conditional ? addClass : removeClass).call(null, targetNode, className)
101
- }
102
-
103
- export function replaceClass(targetNode, removeClassName, addClassName) {
104
- if (removeClassName) removeClass(targetNode, removeClassName);
105
- if (addClassName) addClass(targetNode, addClassName);
106
- }
107
-
108
- export function style(targetNode, name, value) {
109
- if (typeof value === "undefined") return L.DomUtil.getStyle(targetNode, name);
110
- else return targetNode.style.setProperty(name, value);
111
- }
112
-
113
- export function toggleStyle(targetNode, name, value, conditional) {
114
- return style(targetNode, name, conditional ? value : '');
115
- }
116
-
117
- export function toggleEvent(leafletElement, eventName, handler, conditional) {
118
- return leafletElement[conditional ? 'on' : 'off'](eventName, handler);
119
- }
120
-
121
- /**
122
- * A little bit shorter than L.DomUtil.create()
123
- */
124
- export function create(tagName, className, attributes, parent) {
125
- let elem = L.DomUtil.create(tagName, className || "");
126
- if (attributes) setAttributes(elem, attributes);
127
- if (parent) append(parent, elem);
128
- return elem;
90
+ export function coordPropsToMeta(coordProps, name, parser) {
91
+ return coordProps && (({props, point, id}) => {
92
+ if (props) {
93
+ for (const key of coordProps) {
94
+ if (key in props) {
95
+ point.meta[name] = (parser || parseInt).call(this, props[key], id);
96
+ break;
97
+ }
98
+ }
99
+ }
100
+ });
129
101
  }
130
102
 
131
103
  /**
132
- * Same as node.appendChild()
104
+ * Extract numeric property (id) from GeoJSON object
133
105
  */
134
- export function append(parent, child) {
135
- return parent.appendChild(child);
136
- }
106
+ export const parseInt = (property, id) => window.parseInt((typeof property === 'object' ? property[id] : property));
137
107
 
138
108
  /**
139
- * Same as node.insertAdjacentElement()
109
+ * Extract datetime property (id) from GeoJSON object
140
110
  */
141
- export function insert(parent, child, position) {
142
- return parent.insertAdjacentElement(position, child);
143
- }
111
+ export const parseDate = (property, id) => new Date(Date.parse((typeof property === 'object' ? property[id] : property)));
144
112
 
145
113
  /**
146
- * Loop for node.setAttribute()
114
+ * A little bit shorter than L.DomUtil
147
115
  */
148
- export function setAttributes(elem, attrs) {
149
- for (let k in attrs) { elem.setAttribute(k, attrs[k]); }
150
- }
116
+ export const addClass = (n, str) => n && str.split(" ").every(s => s && L.DomUtil.addClass(n, s));
117
+ export const removeClass = (n, str) => n && str.split(" ").every(s => s && L.DomUtil.removeClass(n, s));
118
+ export const toggleClass = (n, str, cond) => (cond ? addClass : removeClass)(n, str);
119
+ export const replaceClass = (n, rem, add) => (rem && removeClass(n, rem)) || (add && addClass(n, add));
120
+ export const style = (n, k, v) => (typeof v === "undefined" && L.DomUtil.getStyle(n, k)) || n.style.setProperty(k, v);
121
+ export const toggleStyle = (n, k, v, cond) => style(n, k, cond ? v : '');
122
+ export const setAttributes = (n, attrs) => { for (let k in attrs) { n.setAttribute(k, attrs[k]); } };
123
+ export const toggleEvent = (el, e, fn, cond) => el[cond ? 'on' : 'off'](e, fn);
124
+ export const create = (tag, str, attrs, n) => { let elem = L.DomUtil.create(tag, str || ""); if (attrs) setAttributes(elem, attrs); if (n) append(n, elem); return elem; };
125
+ export const append = (n, c) => n.appendChild(c);
126
+ export const insert = (n, c, pos) => n.insertAdjacentElement(pos, c);
127
+ export const select = (str, n) => (n || document).querySelector(str);
128
+ export const each = (obj, fn) => { for (let i in obj) fn(obj[i], i); };
129
+ export const randomId = () => Math.random().toString(36).substr(2, 9);
151
130
 
152
131
  /**
153
- * Same as node.querySelector().
132
+ * TODO: use generators instead? (ie. "yield")
154
133
  */
155
- export function select(selector, context) {
156
- return (context || document).querySelector(selector);
157
- }
134
+ export const iMax = (iVal, max) => (iVal > max ? iVal : max) || -Infinity;
135
+ export const iMin = (iVal, min) => (iVal < min ? iVal : min) || +Infinity;
136
+ export const iAvg = (iVal, avg) => (iVal + (avg || 0)) / 2.0;
137
+ export const iSum = (iVal, sum) => iVal + (sum || 0);
158
138
 
159
139
  /**
160
- * Alias for L.DomEvent.on.
140
+ * Alias for some leaflet core functions
161
141
  */
162
- export const on = L.DomEvent.on;
142
+ export const { on, off } = L.DomEvent;
143
+ export const { throttle } = L.Util;
144
+ export const { hasClass } = L.DomUtil;
163
145
 
164
146
  /**
165
- * Alias for L.DomEvent.off.
147
+ * Limit floating point precision
166
148
  */
167
- export const off = L.DomEvent.off;
149
+ export const round = L.Util.formatNum;
168
150
 
169
151
  /**
170
- * Alias for L.DomUtil.hasClass.
171
- */
172
- export const hasClass = L.DomUtil.hasClass;
173
-
174
-
175
- /**
176
- * Generate a random string
152
+ * Limit a number between min / max values
177
153
  */
178
- export function randomId() {
179
- return Math.random().toString(36).substr(2, 9);
180
- }
154
+ export const clamp = (val, range) => range ? (val < range[0] ? range[0] : val > range[1] ? range[1] : val) : val;
181
155
 
182
156
  /**
183
- * Execute a function foreach element in object
157
+ * Limit a delta difference between two values
184
158
  */
185
- export function each(obj, fn) {
186
- for (let i in obj) fn(obj[i], i);
187
- }
159
+ export const wrapDelta = (curr, prev, deltaMax) => Math.abs(curr - prev) > deltaMax ? prev + deltaMax * Math.sign(curr - prev) : curr;
@@ -1,108 +0,0 @@
1
- import 'leaflet-i18n';
2
- import * as _ from './utils';
3
- import * as D3 from './components';
4
- import { Elevation } from './control';
5
-
6
- Elevation.addInitHook(function() {
7
-
8
- if (!this.options.acceleration) return;
9
-
10
- let opts = this.options;
11
- let acceleration = {};
12
-
13
- acceleration.label = opts.accelerationLabel || L._(opts.imperial ? 'ft/s²' : 'm/s²');
14
- opts.accelerationFactor = opts.accelerationFactor || 1;
15
-
16
- if (this.options.acceleration != "summary") {
17
-
18
- this._registerAxisScale({
19
- axis : "y",
20
- position : "right",
21
- scale : {
22
- min : 0,
23
- max : +1,
24
- },
25
- tickPadding: 16,
26
- label : acceleration.label,
27
- labelX : 25,
28
- labelY : -8,
29
- name : 'acceleration'
30
- });
31
-
32
- this._registerAreaPath({
33
- name : 'acceleration',
34
- label : 'Acceleration',
35
- yAttr : 'acceleration',
36
- scaleX : 'distance',
37
- scaleY : 'acceleration',
38
- color : '#050402',
39
- strokeColor : '#000',
40
- strokeOpacity: "0.5",
41
- fillOpacity : "0.25",
42
- });
43
-
44
- }
45
-
46
- this.on('elepoint_added', function(e) {
47
- let data = this._data;
48
- let i = e.index;
49
-
50
- let currT = data[i].time;
51
- let prevT = i > 0 ? data[i - 1].time : currT;
52
-
53
- let deltaT = (currT - prevT) / 1000;
54
-
55
- let track = this.track_info;
56
- let sMax = track.acceleration_max || -Infinity; // Acceleration Max
57
- let sMin = track.acceleration_min || +Infinity; // Acceleration Min
58
- let sAvg = track.acceleration_avg || 0; // Acceleration Avg
59
- let acceleration = 0;
60
-
61
- if (deltaT > 0) {
62
- let curr = data[i].speed;
63
- let prev = i > 0 ? data[i - 1].speed : curr;
64
- let delta = (curr - prev) * (1000 / opts.timeFactor);
65
- acceleration = Math.abs((delta / deltaT)) * opts.accelerationFactor;
66
- }
67
-
68
- // Try to smooth "crazy" acceleration values.
69
- if (this.options.accelerationDeltaMax) {
70
- let deltaA = i > 0 ? acceleration - data[i - 1].acceleration : 0;
71
- let maxDeltaS = this.options.accelerationDeltaMax;
72
- if (Math.abs(deltaA) > maxDeltaS) {
73
- acceleration = data[i - 1].acceleration + maxDeltaS * Math.sign(deltaA);
74
- }
75
- }
76
-
77
- // Range of acceptable acceleration values.
78
- acceleration = _.clamp(acceleration, this.options.accelerationRange);
79
-
80
- track.acceleration_max = acceleration > sMax ? acceleration : sMax;
81
- track.acceleration_min = acceleration < sMin ? acceleration : sMin;
82
- track.acceleration_avg = (acceleration + sAvg) / 2.0;
83
-
84
- data[i].acceleration = L.Util.formatNum(acceleration, 2);
85
- });
86
-
87
- this._registerTooltip({
88
- name : 'acceleration',
89
- chart: (item) => L._("a: ") + item.acceleration + " " + acceleration.label,
90
- marker: (item) => Math.round(item.acceleration) + " " + acceleration.label,
91
- });
92
-
93
- this._registerSummary({
94
- "minacceleration" : {
95
- label: "Min Acceleration: ",
96
- value: (track) => Math.round(track.acceleration_min || 0) + '&nbsp;' + acceleration.label
97
- },
98
- "maxacceleration" : {
99
- label: "Max Acceleration: ",
100
- value: (track) => Math.round(track.acceleration_max || 0) + '&nbsp;' + acceleration.label
101
- },
102
- "avgacceleration": {
103
- label: "Avg Acceleration: ",
104
- value: (track) => Math.round(track.acceleration_avg || 0) + '&nbsp;' + acceleration.label
105
- }
106
- });
107
-
108
- });
package/src/altitude.js DELETED
@@ -1,120 +0,0 @@
1
- import 'leaflet-i18n';
2
- import * as _ from './utils';
3
- import * as D3 from './components';
4
- import { Elevation } from './control';
5
-
6
- Elevation.addInitHook(function() {
7
-
8
- let opts = this.options;
9
- let altitude = {};
10
-
11
- if (opts.imperial) {
12
- opts.altitudeFactor = this.__footFactor;
13
- altitude.label = "ft";
14
- } else {
15
- opts.altitudeFactor = opts.heightFactor || opts.altitudeFactor || 1;
16
- altitude.label = opts.yLabel;
17
- }
18
-
19
- this.on("eledata_updated", function(e) {
20
- let data = this._data;
21
- let i = e.index;
22
- let z = data[i].z * opts.altitudeFactor;
23
-
24
- let track = this.track_info;
25
- let zMax = track.elevation_max || -Infinity;
26
- let zMin = track.elevation_min || +Infinity;
27
-
28
- // check and fix missing elevation data on last added point
29
- if (!this.options.skipNullZCoords && i > 0) {
30
- let prevZ = data[i - 1].z;
31
- if (isNaN(prevZ)) {
32
- let lastZ = this._lastValidZ;
33
- let currZ = z;
34
- if (!isNaN(lastZ) && !isNaN(currZ)) {
35
- prevZ = (lastZ + currZ) / 2;
36
- } else if (!isNaN(lastZ)) {
37
- prevZ = lastZ;
38
- } else if (!isNaN(currZ)) {
39
- prevZ = currZ;
40
- }
41
- if (!isNaN(prevZ)) return data.splice(i - 1, 1);
42
- data[i - 1].z = prevZ;
43
- }
44
- }
45
- // skip point if it has not elevation
46
- if (!isNaN(z)) {
47
- this._lastValidZ = z;
48
- }
49
-
50
- track.elevation_max = z > zMax ? z : zMax;
51
- track.elevation_min = z < zMin ? z : zMin;
52
-
53
- data[i].z = z;
54
- });
55
-
56
- this.on("elechart_axis", function() {
57
-
58
- this._chart._registerAxisGrid({
59
- axis : "y",
60
- position : "left",
61
- scale : this._chart._y,
62
- });
63
-
64
- });
65
-
66
- if (this.options.altitude != "summary") {
67
-
68
- this.on("elechart_axis", function() {
69
-
70
- this._chart._registerAxisScale({
71
- axis : "y",
72
- position: "left",
73
- scale : this._chart._y,
74
- label : altitude.label,
75
- labelX : -3,
76
- labelY : -8,
77
- name : "altitude",
78
- });
79
-
80
- });
81
-
82
- this.on("elechart_init", function() {
83
-
84
- let theme = this.options.theme.replace('-theme', '');
85
- let color = D3.Colors[theme] || {};
86
-
87
- this._chart._registerAreaPath({
88
- name : 'altitude',
89
- label : 'Altitude',
90
- scaleX : 'distance',
91
- scaleY : 'altitude',
92
- color : color.area || theme,
93
- strokeColor : this.options.detached ? color.stroke : '#000',
94
- strokeOpacity: "1",
95
- fillOpacity : this.options.detached ? (color.alpha || '0.8') : 1,
96
- preferCanvas : this.options.preferCanvas,
97
- });
98
-
99
- });
100
-
101
- }
102
-
103
- this._registerTooltip({
104
- name: 'y',
105
- chart: (item) => L._("y: ") + d3.format("." + opts.decimalsY + "f")(item[opts.yAttr]) + " " + altitude.label,
106
- marker: (item) => d3.format("." + opts.decimalsY + "f")(item[opts.yAttr]) + " " + altitude.label,
107
- });
108
-
109
- this._registerSummary({
110
- "maxele" : {
111
- label: "Max Elevation: ",
112
- value: (track) => (track.elevation_max || 0).toFixed(2) + '&nbsp;' + altitude.label
113
- },
114
- "minele" : {
115
- label: "Min Elevation: ",
116
- value: (track) => (track.elevation_min || 0).toFixed(2) + '&nbsp;' + altitude.label
117
- },
118
- });
119
-
120
- });
package/src/distance.js DELETED
@@ -1,78 +0,0 @@
1
- import 'leaflet-i18n';
2
- import * as _ from './utils';
3
- import * as D3 from './components';
4
- import { Elevation } from './control';
5
-
6
- Elevation.addInitHook(function() {
7
-
8
- let opts = this.options;
9
- let distance = {};
10
-
11
- if (opts.imperial) {
12
- opts.distanceFactor = this.__mileFactor;
13
- distance.label = "mi";
14
- } else {
15
- opts.distanceFactor = opts.distanceFactor || 1;
16
- distance.label = opts.xLabel;
17
- }
18
-
19
- this.on("eledata_updated", function(e) {
20
- let data = this._data;
21
- let i = e.index;
22
-
23
- let track = this.track_info;
24
- let dist = track.distance || 0;
25
-
26
- let curr = data[i].latlng;
27
- let prev = i > 0 ? data[i - 1].latlng : curr;
28
-
29
- let delta = curr.distanceTo(prev) * opts.distanceFactor;
30
-
31
- dist += Math.round(delta / 1000 * 100000) / 100000; // handles floating points calc
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
-
46
- });
47
-
48
- if (this.options.distance != "summary") {
49
-
50
- this.on("elechart_axis", function() {
51
-
52
- this._chart._registerAxisScale({
53
- axis : "x",
54
- position: "bottom",
55
- scale : this._chart._x,
56
- label : distance.label,
57
- labelY : 25,
58
- labelX : () => this._width() + 6,
59
- name : "distance",
60
- });
61
-
62
- });
63
-
64
- }
65
-
66
- this._registerTooltip({
67
- name: 'x',
68
- chart: (item) => L._("x: ") + d3.format("." + opts.decimalsX + "f")(item[opts.xAttr]) + " " + distance.label,
69
- });
70
-
71
- this._registerSummary({
72
- "totlen" : {
73
- label: "Total Length: ",
74
- value: (track) => (track.distance || 0).toFixed(2) + '&nbsp;' + distance.label
75
- }
76
- });
77
-
78
- });
package/src/slope.js DELETED
@@ -1,113 +0,0 @@
1
- import 'leaflet-i18n';
2
- import * as _ from './utils';
3
- import * as D3 from './components';
4
- import { Elevation } from './control';
5
-
6
- Elevation.addInitHook(function() {
7
-
8
- if (!this.options.slope) return;
9
-
10
- let opts = this.options;
11
- let slope = {};
12
-
13
- slope.label = opts.slopeLabel || '%';
14
-
15
- if (this.options.slope != "summary") {
16
-
17
- this._registerAxisScale({
18
- axis : "y",
19
- position : "right",
20
- scale : {
21
- min : -1,
22
- max : +1,
23
- },
24
- tickPadding: 16,
25
- label : slope.label,
26
- labelX : 25,
27
- labelY : -8,
28
- name : 'slope'
29
- });
30
-
31
- this._registerAreaPath({
32
- name : 'slope',
33
- label : 'Slope',
34
- yAttr : 'slope',
35
- scaleX : 'distance',
36
- scaleY : 'slope',
37
- color : '#F00',
38
- strokeColor : '#000',
39
- strokeOpacity: "0.5",
40
- fillOpacity : "0.25",
41
- });
42
-
43
- }
44
-
45
- this.on("eledata_updated", function(e) {
46
- let data = this._data;
47
- let i = e.index;
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);
73
- }
74
- }
75
-
76
- // Range of acceptable slope values.
77
- slope = _.clamp(slope, this.options.sRange);
78
-
79
- track.ascent = tAsc;
80
- track.descent = tDes;
81
- track.slope_max = slope > sMax ? slope : sMax;
82
- track.slope_min = slope < sMin ? slope : sMin;
83
-
84
- data[i].slope = L.Util.formatNum(slope, 2);
85
- });
86
-
87
- this._registerTooltip({
88
- name: 'slope',
89
- chart: (item) => L._("m: ") + item.slope + slope.label,
90
- marker: (item) => Math.round(item.slope) + slope.label
91
- });
92
-
93
- this._registerSummary({
94
- "ascent" : {
95
- label: "Total Ascent: ",
96
- value: (track) => Math.round(track.ascent || 0) + '&nbsp;' + (this.options.imperial ? 'ft' : 'm')
97
- },
98
- "descent" : {
99
- label: "Total Descent: ",
100
- value: (track) => Math.round(track.descent || 0) + '&nbsp;' + (this.options.imperial ? 'ft' : 'm')
101
- },
102
- "minslope": {
103
- label: "Min Slope: ",
104
- value: (track) => Math.round(track.slope_min || 0) + '&nbsp;' + slope.label
105
- },
106
- "maxslope": {
107
- label: "Max Slope: ",
108
- value: (track) => Math.round(track.slope_max || 0) + '&nbsp;' + slope.label
109
- }
110
- });
111
-
112
-
113
- });