@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/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.3/libs/leaflet-distance-marker.min.js',
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 when "followMarker" is true.
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 = { lazy: true };
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 KML).
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 when "followMarker" is true.
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
- if (props) {
352
- if("coordTimes" in props) point.meta.time = new Date(Date.parse(props.coordTimes[i]));
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._fireEvt("elepoint_added", { point: point, index: this._data.length - 1 });
374
+ this.fire("elepoint_added", { point: point, index: this._data.length - 1 });
368
375
  });
369
376
 
370
- this._fireEvt("eletrack_added", { coords: coords, index: this._data.length - 1 });
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._fireEvt("eledata_updated", { index: this._data.length - 1 });
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._fireEvt.bind('elechart_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._fireEvt("elechart_axis");
616
- if (this.options.legend) this._fireEvt("elechart_legend");
622
+ this.fire("elechart_axis");
623
+
624
+ if (this.options.legend) this.fire("elechart_legend");
617
625
 
618
- this._fireEvt("elechart_init");
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._fireEvt("elechart_marker");
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._fireEvt("elechart_dragged");
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._fireEvt("elechart_change", { data: item, xCoord: xCoord });
800
- this._fireEvt("elechart_hover", { data: item, xCoord: xCoord });
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._fireEvt("elechart_change", { data: item, xCoord: xCoord });
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._fireEvt("elechart_leave");
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 current chart control.
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
- * Sets the view of the map (center and zoom). Useful when "followMarker" is true.
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._fireEvt("elechart_axis");
1084
- this._fireEvt("elechart_area");
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._fireEvt('elechart_updated');
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._fireEvt("elechart_summary");
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._fireEvt('eletrack_download', event);
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.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
-
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.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
-
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) + '&nbsp;' + distance.label
64
+ value: (track) => (track.distance || 0).toFixed(2) + '&nbsp;' + 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: false,
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
- sLimit: undefined,
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
- 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);
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
- // Range of acceptable slope values.
77
- slope = _.clamp(slope, this.options.sRange);
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
- track.ascent = tAsc;
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
- data[i].slope = L.Util.formatNum(slope, 2);
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) + '&nbsp;' + (this.options.imperial ? 'ft' : 'm')
103
+ value: (track) => Math.round(track.ascent || 0) + '&nbsp;' + (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) + '&nbsp;' + (this.options.imperial ? 'ft' : 'm')
108
+ value: (track) => Math.round(track.descent || 0) + '&nbsp;' + (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) + '&nbsp;' + slope.label
113
+ value: (track) => Math.round(track.slope_min || 0) + '&nbsp;' + slope.label,
114
+ order: 40
105
115
  },
106
116
  "maxslope": {
107
117
  label: "Max Slope: ",
108
- value: (track) => Math.round(track.slope_max || 0) + '&nbsp;' + slope.label
118
+ value: (track) => Math.round(track.slope_max || 0) + '&nbsp;' + slope.label,
119
+ order: 40
120
+ },
121
+ "avgslope": {
122
+ label: "Avg Slope: ",
123
+ value: (track) => Math.round(track.slope_avg || 0) + '&nbsp;' + slope.label,
124
+ order: 40
109
125
  }
110
126
  });
111
127