@raruto/leaflet-elevation 2.0.0 → 2.0.3
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 +2 -1
- package/dist/leaflet-elevation.css +3 -1
- package/dist/leaflet-elevation.js +148 -189
- package/dist/leaflet-elevation.js.map +1 -1
- package/dist/leaflet-elevation.min.css +1 -1
- package/dist/leaflet-elevation.min.js +1 -1
- package/dist/leaflet-elevation.min.js.map +1 -1
- package/libs/leaflet-distance-marker.js +97 -92
- package/libs/leaflet-distance-marker.min.js +1 -1
- package/package.json +1 -1
- package/src/{chart.js → components/chart.js} +78 -54
- package/src/{components.js → components/d3.js} +74 -16
- package/src/{marker.js → components/marker.js} +1 -1
- package/src/{summary.js → components/summary.js} +0 -0
- package/src/control.js +141 -184
- package/src/handlers/altitude.js +4 -1
- package/src/handlers/heart.js +2 -2
- package/src/index.css +3 -1
- package/src/utils.js +5 -5
- package/src/handlers/acceleration.min.js +0 -1
- package/src/handlers/altitude.min.js +0 -1
- package/src/handlers/distance.min.js +0 -1
- package/src/handlers/slope.min.js +0 -1
- package/src/handlers/speed.min.js +0 -1
- package/src/handlers/time.min.js +0 -1
package/src/control.js
CHANGED
|
@@ -14,10 +14,10 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
14
14
|
__LGEOMUTIL: 'https://unpkg.com/leaflet-geometryutil@0.9.3/src/leaflet.geometryutil.js',
|
|
15
15
|
__LALMOSTOVER: 'https://unpkg.com/leaflet-almostover@1.0.1/src/leaflet.almostover.js',
|
|
16
16
|
__LDISTANCEM: '../libs/leaflet-distance-marker.min.js',
|
|
17
|
+
__LCHART: '../src/components/chart.js',
|
|
18
|
+
__LMARKER: '../src/components/marker.js',
|
|
19
|
+
__LSUMMARY: '../src/components/summary.js',
|
|
17
20
|
__modulesFolder: '../src/handlers/',
|
|
18
|
-
__LCHART: '../src/chart.js',
|
|
19
|
-
__LMARKER: '../src/marker.js',
|
|
20
|
-
__LSUMMARY: '../src/summary.js',
|
|
21
21
|
|
|
22
22
|
/*
|
|
23
23
|
* Add data to the diagram either from GPX or GeoJSON and update the axis domain and data
|
|
@@ -25,9 +25,7 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
25
25
|
addData: function(d, layer) {
|
|
26
26
|
this.import(this.__D3)
|
|
27
27
|
.then(() => {
|
|
28
|
-
|
|
29
|
-
layer = d;
|
|
30
|
-
}
|
|
28
|
+
layer = layer ?? (d.on && d);
|
|
31
29
|
this._addData(d);
|
|
32
30
|
this._addLayer(layer);
|
|
33
31
|
this._fireEvt("eledata_added", { data: d, layer: layer, track_info: this.track_info });
|
|
@@ -296,51 +294,44 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
296
294
|
return;
|
|
297
295
|
}
|
|
298
296
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
this._addGeoJSONData(geom.coordinates);
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
break;
|
|
312
|
-
|
|
313
|
-
default:
|
|
314
|
-
return console.warn('Unsopperted GeoJSON feature geometry type:' + geom.type);
|
|
297
|
+
// Standard GeoJSON
|
|
298
|
+
if (d.type === "FeatureCollection" ) {
|
|
299
|
+
return _.each(d.features, feature => this._addData(feature));
|
|
300
|
+
} else if (d.type === "Feature") {
|
|
301
|
+
let geom = d.geometry;
|
|
302
|
+
if (geom) {
|
|
303
|
+
switch (geom.type) {
|
|
304
|
+
case 'LineString': return this._addGeoJSONData(geom.coordinates, d.properties);
|
|
305
|
+
case 'MultiLineString': return _.each(geom.coordinates, (coords, i) => this._addGeoJSONData(coords, d.properties, i));
|
|
306
|
+
case 'Point':
|
|
307
|
+
default: return console.warn('Unsopperted GeoJSON feature geometry type:' + geom.type);
|
|
308
|
+
}
|
|
315
309
|
}
|
|
316
310
|
}
|
|
317
|
-
if (d.type === "FeatureCollection") {
|
|
318
|
-
_.each(d.features, feature => this._addData(feature));
|
|
319
|
-
}
|
|
320
311
|
|
|
321
|
-
|
|
322
|
-
* Extended GeoJSON --> rely on leaflet implementation
|
|
323
|
-
*/
|
|
312
|
+
// Fallback for leaflet layers (eg. L.Gpx)
|
|
324
313
|
if (d._latlngs) {
|
|
325
|
-
this._addGeoJSONData(d._latlngs, d.feature && d.feature.properties);
|
|
314
|
+
return this._addGeoJSONData(d._latlngs, d.feature && d.feature.properties);
|
|
326
315
|
}
|
|
316
|
+
|
|
327
317
|
},
|
|
328
318
|
|
|
329
319
|
/*
|
|
330
320
|
* Parsing of GeoJSON data lines and their elevation in z-coordinate
|
|
331
321
|
*/
|
|
332
|
-
_addGeoJSONData: function(coords, properties) {
|
|
322
|
+
_addGeoJSONData: function(coords, properties, nestingLevel) {
|
|
323
|
+
|
|
324
|
+
// "coordinateProperties" property is generated inside "@tmcw/toGeoJSON"
|
|
325
|
+
let props = (properties && properties.coordinateProperties) || properties;
|
|
326
|
+
|
|
333
327
|
coords.forEach((point, i) => {
|
|
334
328
|
|
|
335
329
|
// GARMIN_EXTENSIONS = ["hr", "cad", "atemp", "wtemp", "depth", "course", "bearing"];
|
|
336
330
|
point.meta = point.meta ?? { time: null, ele: null };
|
|
337
331
|
|
|
338
|
-
// "coordinateProperties" property is generated inside "@tmcw/toGeoJSON"
|
|
339
|
-
let props = (properties && properties.coordinateProperties) || properties;
|
|
340
|
-
|
|
341
332
|
point.prev = (attr) => (attr ? this._data[i > 0 ? i - 1 : 0][attr] : this._data[i > 0 ? i - 1 : 0]);
|
|
342
333
|
|
|
343
|
-
this.fire("elepoint_init", { point: point, props: props, id: i });
|
|
334
|
+
this.fire("elepoint_init", { point: point, props: props, id: i, isMulti: nestingLevel });
|
|
344
335
|
|
|
345
336
|
this._addPoint(
|
|
346
337
|
point.lat ?? point[1],
|
|
@@ -380,10 +371,12 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
380
371
|
if (layer && this.options.distanceMarkers && this.options.distanceMarkers.lazy) {
|
|
381
372
|
layer.on('add remove', ({target, type}) => L.DistanceMarkers && target instanceof L.Polyline && target[type + 'DistanceMarkers']());
|
|
382
373
|
}
|
|
374
|
+
return layer;
|
|
383
375
|
},
|
|
384
376
|
|
|
385
377
|
_addMarker: function(marker) {
|
|
386
378
|
if (marker) this._markers.addLayer(marker)
|
|
379
|
+
return marker;
|
|
387
380
|
},
|
|
388
381
|
|
|
389
382
|
/**
|
|
@@ -600,10 +593,6 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
600
593
|
.on('margins_updated', this._resizeChart, this);
|
|
601
594
|
|
|
602
595
|
|
|
603
|
-
this.fire("elechart_axis");
|
|
604
|
-
|
|
605
|
-
if (this.options.legend) this.fire("elechart_legend");
|
|
606
|
-
|
|
607
596
|
this.fire("elechart_init");
|
|
608
597
|
|
|
609
598
|
map
|
|
@@ -716,7 +705,7 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
716
705
|
*/
|
|
717
706
|
_loadModules: function(handlers) {
|
|
718
707
|
// First map known classnames (eg. "Altitude" --> L.Control.Elevation.Altitude)
|
|
719
|
-
handlers = handlers.map((h) => typeof h === 'string' && typeof
|
|
708
|
+
handlers = handlers.map((h) => typeof h === 'string' && typeof Elevation[h] !== "undefined" ? Elevation[h] : h);
|
|
720
709
|
// Then load optional classes and custom imports (eg. "Cadence" --> import('../src/handlers/cadence.js'))
|
|
721
710
|
Promise.
|
|
722
711
|
all(
|
|
@@ -727,8 +716,8 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
727
716
|
.then((m) => {
|
|
728
717
|
_.each(m, (exported) => {
|
|
729
718
|
let fn = Object.keys(exported)[0];
|
|
730
|
-
if (fn && typeof
|
|
731
|
-
handlers[fn] =
|
|
719
|
+
if (fn && typeof Elevation[fn] === "undefined" ) {
|
|
720
|
+
handlers[fn] = Elevation[fn] = exported[fn];
|
|
732
721
|
|
|
733
722
|
}
|
|
734
723
|
});
|
|
@@ -740,65 +729,48 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
740
729
|
* Simple GeoJSON data loader (L.GeoJSON).
|
|
741
730
|
*/
|
|
742
731
|
_loadLayer: function(geojson) {
|
|
743
|
-
let
|
|
732
|
+
let { polyline, theme, waypoints, wptIcons, wptLabels, distanceMarkers } = this.options;
|
|
733
|
+
let style = L.extend({}, polyline);
|
|
734
|
+
|
|
735
|
+
if (theme) {
|
|
736
|
+
style.className += ' ' + theme;
|
|
737
|
+
}
|
|
744
738
|
|
|
745
|
-
|
|
739
|
+
if (geojson.name) {
|
|
740
|
+
this.track_info.name = geojson.name;
|
|
741
|
+
}
|
|
746
742
|
|
|
747
743
|
let layer = L.geoJson(geojson, {
|
|
748
|
-
distanceMarkers:
|
|
749
|
-
style:
|
|
750
|
-
let style = L.extend({}, control.options.polyline);
|
|
751
|
-
if (control.options.theme) {
|
|
752
|
-
style.className += ' ' + control.options.theme;
|
|
753
|
-
}
|
|
754
|
-
return style;
|
|
755
|
-
},
|
|
744
|
+
distanceMarkers: distanceMarkers,
|
|
745
|
+
style: style,
|
|
756
746
|
pointToLayer: (feature, latlng) => {
|
|
757
|
-
if (
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
latlng: latlng,
|
|
768
|
-
label: ([true, 'dots'].includes(wptLabels) ? name : '')
|
|
769
|
-
});
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
// Handle map waypoints (markers)
|
|
773
|
-
if ([true, 'markers'].includes(control.options.waypoints) && wptIcons != false) {
|
|
774
|
-
// generate and cache appropriate icon symbol
|
|
775
|
-
if (!wptIcons.hasOwnProperty(sym)) {
|
|
776
|
-
wptIcons[sym] = L.divIcon(
|
|
777
|
-
L.extend({}, wptIcons[""].options, { html: '<i class="elevation-waypoint-icon ' + sym + '"></i>' } )
|
|
778
|
-
);
|
|
747
|
+
if (waypoints) {
|
|
748
|
+
let { desc, name, sym } = feature.properties;
|
|
749
|
+
desc = desc || '';
|
|
750
|
+
name = name || '';
|
|
751
|
+
// Handle chart waypoints (dots)
|
|
752
|
+
if ([true, 'dots'].includes(waypoints)) {
|
|
753
|
+
this._registerCheckPoint({
|
|
754
|
+
latlng: latlng,
|
|
755
|
+
label : ([true, 'dots'].includes(wptLabels) ? name : '')
|
|
756
|
+
});
|
|
779
757
|
}
|
|
780
|
-
|
|
781
|
-
if ([true, 'markers'].includes(
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
758
|
+
// Handle map waypoints (markers)
|
|
759
|
+
if ([true, 'markers'].includes(waypoints) && wptIcons != false) {
|
|
760
|
+
return this._registerMarker({
|
|
761
|
+
latlng : latlng,
|
|
762
|
+
sym : (sym ?? name).replace(' ', '-').replace('"', '').replace("'", '').toLowerCase(),
|
|
763
|
+
content: [true, 'markers'].includes(wptLabels) && (name || desc) && decodeURI("<b>" + name + "</b>" + (desc.length > 0 ? '<br>' + desc : ''))
|
|
764
|
+
});
|
|
785
765
|
}
|
|
786
|
-
control._addMarker(marker);
|
|
787
|
-
control.fire('waypoint_added', { point: marker, element: latlng, properties: prop });
|
|
788
|
-
return marker;
|
|
789
766
|
}
|
|
790
767
|
},
|
|
791
|
-
onEachFeature: (feature, layer) =>
|
|
792
|
-
if (feature.geometry && feature.geometry.type != 'Point') {
|
|
793
|
-
control.addData(layer);
|
|
794
|
-
control.track_info = L.extend({}, control.track_info, { name: geojson.name });
|
|
795
|
-
}
|
|
796
|
-
},
|
|
768
|
+
onEachFeature: (feature, layer) => feature.geometry && feature.geometry.type != 'Point' && this.addData(feature, layer),
|
|
797
769
|
});
|
|
798
770
|
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
771
|
+
this.import(this.__D3).then(() => {
|
|
772
|
+
this._initMapIntegrations(this, layer);
|
|
773
|
+
this._fireEvt("eledata_loaded", { data: geojson, layer: layer, name: this.track_info.name, track_info: this.track_info });
|
|
802
774
|
});
|
|
803
775
|
|
|
804
776
|
return layer;
|
|
@@ -929,8 +901,7 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
929
901
|
geojson = this._parseFromGeoJSONString(data.toString());
|
|
930
902
|
}
|
|
931
903
|
if (geojson) {
|
|
932
|
-
geojson = this.
|
|
933
|
-
geojson = this._prepareAdditionalProperties(geojson);
|
|
904
|
+
geojson.name = geojson.name || (this._downloadURL || '').split('/').pop().split('#')[0].split('?')[0];
|
|
934
905
|
}
|
|
935
906
|
resolve(geojson);
|
|
936
907
|
})
|
|
@@ -958,37 +929,6 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
958
929
|
return geojson;
|
|
959
930
|
},
|
|
960
931
|
|
|
961
|
-
/**
|
|
962
|
-
* Extend GeoJSON properties (name, time, ...)
|
|
963
|
-
*/
|
|
964
|
-
_prepareAdditionalProperties: function(geojson) {
|
|
965
|
-
if (!geojson.name && this._downloadURL) {
|
|
966
|
-
geojson.name = this._downloadURL.split('/').pop().split('#')[0].split('?')[0];
|
|
967
|
-
}
|
|
968
|
-
return geojson;
|
|
969
|
-
},
|
|
970
|
-
|
|
971
|
-
/**
|
|
972
|
-
* Just a temporary fix for MultiLineString data (trk > trkseg + trkseg),
|
|
973
|
-
* just split them into seperate LineStrings (trk > trkseg, trk > trkseg)
|
|
974
|
-
*
|
|
975
|
-
* @link https://github.com/Raruto/leaflet-elevation/issues/56
|
|
976
|
-
*/
|
|
977
|
-
_prepareMultiLineStrings: function(geojson) {
|
|
978
|
-
geojson.features.forEach(feauture => {
|
|
979
|
-
if (feauture.geometry.type == "MultiLineString") {
|
|
980
|
-
feauture.geometry.coordinates.forEach(coords => {
|
|
981
|
-
geojson.features.push({
|
|
982
|
-
geometry: { type: 'LineString', coordinates: coords },
|
|
983
|
-
properties: feauture.properties,
|
|
984
|
-
type: 'Feature'
|
|
985
|
-
});
|
|
986
|
-
});
|
|
987
|
-
}
|
|
988
|
-
});
|
|
989
|
-
return geojson.features.filter(feauture => feauture.geometry.type != "MultiLineString");
|
|
990
|
-
},
|
|
991
|
-
|
|
992
932
|
/**
|
|
993
933
|
* Add chart profile to diagram
|
|
994
934
|
*/
|
|
@@ -1106,60 +1046,79 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
1106
1046
|
return this._registerHandler(props.call(this));
|
|
1107
1047
|
}
|
|
1108
1048
|
|
|
1049
|
+
let {
|
|
1050
|
+
name,
|
|
1051
|
+
attr,
|
|
1052
|
+
required,
|
|
1053
|
+
skipNull,
|
|
1054
|
+
deltaMax,
|
|
1055
|
+
clampRange,
|
|
1056
|
+
decimals,
|
|
1057
|
+
meta,
|
|
1058
|
+
unit,
|
|
1059
|
+
coordinateProperties,
|
|
1060
|
+
coordPropsToMeta,
|
|
1061
|
+
pointToAttr,
|
|
1062
|
+
onPointAdded,
|
|
1063
|
+
stats,
|
|
1064
|
+
statsName,
|
|
1065
|
+
grid,
|
|
1066
|
+
scale,
|
|
1067
|
+
path,
|
|
1068
|
+
tooltip,
|
|
1069
|
+
summary
|
|
1070
|
+
} = props;
|
|
1071
|
+
|
|
1109
1072
|
// eg. "altitude" == true
|
|
1110
|
-
if (this.options[
|
|
1073
|
+
if (this.options[name] || required) {
|
|
1111
1074
|
|
|
1112
1075
|
this._registerDataAttribute({
|
|
1113
|
-
name
|
|
1114
|
-
attr
|
|
1115
|
-
skipNull
|
|
1116
|
-
deltaMax
|
|
1117
|
-
clampRange
|
|
1118
|
-
decimals
|
|
1119
|
-
coordPropsToMeta: _.coordPropsToMeta(
|
|
1120
|
-
pointToAttr
|
|
1121
|
-
onPointAdded
|
|
1122
|
-
stats
|
|
1123
|
-
statsName
|
|
1076
|
+
name,
|
|
1077
|
+
attr,
|
|
1078
|
+
skipNull,
|
|
1079
|
+
deltaMax,
|
|
1080
|
+
clampRange,
|
|
1081
|
+
decimals,
|
|
1082
|
+
coordPropsToMeta: _.coordPropsToMeta(coordinateProperties, meta || name, coordPropsToMeta),
|
|
1083
|
+
pointToAttr,
|
|
1084
|
+
onPointAdded,
|
|
1085
|
+
stats,
|
|
1086
|
+
statsName,
|
|
1124
1087
|
});
|
|
1125
1088
|
|
|
1126
|
-
if (
|
|
1127
|
-
|
|
1128
|
-
this._registerAxisGrid(props.grid);
|
|
1089
|
+
if (grid) {
|
|
1090
|
+
this._registerAxisGrid(L.extend({ name }, grid));
|
|
1129
1091
|
}
|
|
1130
1092
|
|
|
1131
|
-
if (this.options[
|
|
1132
|
-
if (
|
|
1133
|
-
|
|
1134
|
-
props.scale.label = props.scale.label || props.unit;
|
|
1135
|
-
this._registerAxisScale(props.scale);
|
|
1136
|
-
}
|
|
1137
|
-
if (props.path) {
|
|
1138
|
-
props.path.name = props.path.name || props.name;
|
|
1139
|
-
this._registerAreaPath(props.path);
|
|
1140
|
-
}
|
|
1093
|
+
if (this.options[name] !== "summary") {
|
|
1094
|
+
if (scale) this._registerAxisScale(L.extend({ name, label: unit }, scale));
|
|
1095
|
+
if (path) this._registerAreaPath(L.extend({ name }, path));
|
|
1141
1096
|
}
|
|
1142
1097
|
|
|
1143
|
-
if (props.tooltips) {
|
|
1144
|
-
_.each(props.tooltips, t => {
|
|
1145
|
-
if (t) {
|
|
1146
|
-
t.name = t.name || props.name;
|
|
1147
|
-
this._registerTooltip(t)
|
|
1148
|
-
}
|
|
1149
|
-
});
|
|
1150
|
-
} else if (props.tooltip) {
|
|
1151
|
-
props.tooltip.name = props.tooltip.name || props.name;
|
|
1152
|
-
this._registerTooltip(props.tooltip)
|
|
1098
|
+
if (tooltip || props.tooltips) {
|
|
1099
|
+
_.each([tooltip, ...(props.tooltips || [])], t => t && this._registerTooltip(L.extend({ name }, t)));
|
|
1153
1100
|
}
|
|
1154
1101
|
|
|
1155
|
-
if (
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
}
|
|
1159
|
-
this._registerSummary(props.summary);
|
|
1102
|
+
if (summary) {
|
|
1103
|
+
_.each(summary, (s, k) => summary[k] = L.extend({ unit }, s));
|
|
1104
|
+
this._registerSummary(summary);
|
|
1160
1105
|
}
|
|
1161
1106
|
}
|
|
1162
1107
|
},
|
|
1108
|
+
|
|
1109
|
+
_registerMarker({latlng, sym, content}) {
|
|
1110
|
+
let { wptIcons } = this.options;
|
|
1111
|
+
// generate and cache appropriate icon symbol
|
|
1112
|
+
if (!wptIcons.hasOwnProperty(sym)) {
|
|
1113
|
+
wptIcons[sym] = L.divIcon(L.extend({}, wptIcons[""].options, { html: '<i class="elevation-waypoint-icon ' + sym + '"></i>' } ));
|
|
1114
|
+
}
|
|
1115
|
+
let marker = L.marker(latlng, { icon: wptIcons[sym] });
|
|
1116
|
+
if (content) {
|
|
1117
|
+
marker.bindPopup(content, { className: 'elevation-popup', keepInView: true }).openPopup();
|
|
1118
|
+
marker.bindTooltip(content, { className: 'elevation-tooltip', direction: 'auto', sticky: true, opacity: 1 }).openTooltip();
|
|
1119
|
+
}
|
|
1120
|
+
return this._addMarker(marker)
|
|
1121
|
+
},
|
|
1163
1122
|
|
|
1164
1123
|
/**
|
|
1165
1124
|
* Add chart or marker tooltip info
|
|
@@ -1242,7 +1201,6 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
1242
1201
|
_updateChart: function() {
|
|
1243
1202
|
if (this._chart && this._container) {
|
|
1244
1203
|
this.fire("elechart_axis");
|
|
1245
|
-
this.fire("elechart_area");
|
|
1246
1204
|
|
|
1247
1205
|
this._chart.update({ data: this._data, options: this.options });
|
|
1248
1206
|
|
|
@@ -1290,27 +1248,26 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
1290
1248
|
* Update chart summary.
|
|
1291
1249
|
*/
|
|
1292
1250
|
_updateSummary: function() {
|
|
1293
|
-
if (
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
this.
|
|
1251
|
+
if (this._summary) {
|
|
1252
|
+
this._summary.reset();
|
|
1253
|
+
if (this.options.summary) {
|
|
1254
|
+
this.fire("elechart_summary");
|
|
1255
|
+
this._summary.update();
|
|
1256
|
+
}
|
|
1257
|
+
if (this.options.downloadLink && this._downloadURL) { // TODO: generate dynamically file content instead of using static file urls.
|
|
1258
|
+
this._summary._container.innerHTML += '<span class="download"><a href="#">' + L._('Download') + '</a></span>'
|
|
1259
|
+
_.select('.download a', this._summary._container).onclick = ({preventDefault}) => {
|
|
1260
|
+
preventDefault();
|
|
1261
|
+
let event = { downloadLink: this.options.downloadLink, confirm: _.saveFile.bind(this, this._downloadURL) };
|
|
1262
|
+
if (this.options.downloadLink == 'modal' && typeof CustomEvent === "function") {
|
|
1263
|
+
document.dispatchEvent(new CustomEvent("eletrack_download", { detail: event }));
|
|
1264
|
+
} else if (this.options.downloadLink == 'link' || this.options.downloadLink === true) {
|
|
1265
|
+
event.confirm();
|
|
1266
|
+
}
|
|
1267
|
+
this.fire('eletrack_download', event);
|
|
1268
|
+
};
|
|
1269
|
+
}
|
|
1300
1270
|
}
|
|
1301
|
-
if (this.options.downloadLink && this._downloadURL) { // TODO: generate dynamically file content instead of using static file urls.
|
|
1302
|
-
this._summary._container.innerHTML += '<span class="download"><a href="#">' + L._('Download') + '</a></span>'
|
|
1303
|
-
_.select('.download a', this._summary._container).onclick = ({preventDefault}) => {
|
|
1304
|
-
preventDefault();
|
|
1305
|
-
let event = { downloadLink: this.options.downloadLink, confirm: _.saveFile.bind(this, this._downloadURL) };
|
|
1306
|
-
if (this.options.downloadLink == 'modal' && typeof CustomEvent === "function") {
|
|
1307
|
-
document.dispatchEvent(new CustomEvent("eletrack_download", { detail: event }));
|
|
1308
|
-
} else if (this.options.downloadLink == 'link' || this.options.downloadLink === true) {
|
|
1309
|
-
event.confirm();
|
|
1310
|
-
}
|
|
1311
|
-
this.fire('eletrack_download', event);
|
|
1312
|
-
};
|
|
1313
|
-
};
|
|
1314
1271
|
},
|
|
1315
1272
|
|
|
1316
1273
|
|
package/src/handlers/altitude.js
CHANGED
|
@@ -24,7 +24,10 @@ export function Altitude() {
|
|
|
24
24
|
// // "alt" property is generated inside "leaflet"
|
|
25
25
|
// if ("alt" in point) point.meta.ele = point.alt;
|
|
26
26
|
// },
|
|
27
|
-
pointToAttr: (
|
|
27
|
+
pointToAttr: (point, i) => {
|
|
28
|
+
if ("alt" in point) point.meta.ele = point.alt; // "alt" property is generated inside "leaflet"
|
|
29
|
+
return this._data[i].z * opts.altitudeFactor;
|
|
30
|
+
},
|
|
28
31
|
stats: { max: _.iMax, min: _.iMin, avg: _.iAvg },
|
|
29
32
|
grid: {
|
|
30
33
|
axis : "y",
|
package/src/handlers/heart.js
CHANGED
package/src/index.css
CHANGED
|
@@ -60,6 +60,7 @@
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
.elevation-control.elevation .axis text,
|
|
63
|
+
.elevation-control.elevation .legend text,
|
|
63
64
|
.elevation-control.elevation .point text {
|
|
64
65
|
fill: #000;
|
|
65
66
|
font-weight: 700;
|
|
@@ -246,7 +247,7 @@
|
|
|
246
247
|
.leaflet-elevation-pane .height-focus,
|
|
247
248
|
.leaflet-overlay-pane .height-focus {
|
|
248
249
|
stroke: #000;
|
|
249
|
-
fill: var(--ele-area, #FFF);
|
|
250
|
+
fill: var(--ele-circle, var(--ele-area, #FFF));
|
|
250
251
|
}
|
|
251
252
|
|
|
252
253
|
.leaflet-elevation-pane .height-focus.line,
|
|
@@ -334,6 +335,7 @@
|
|
|
334
335
|
--ele-area: #3366CC;
|
|
335
336
|
--ele-alpha: 0.45;
|
|
336
337
|
--ele-stroke: #4682B4;
|
|
338
|
+
--ele-circle: #fff;
|
|
337
339
|
}
|
|
338
340
|
|
|
339
341
|
.elevation-detached .lightblue-theme.elevation-control.elevation .area {
|
package/src/utils.js
CHANGED
|
@@ -88,11 +88,11 @@ export function formatTime(t) {
|
|
|
88
88
|
* Loop and extract GPX Extensions handled by "@tmcw/toGeoJSON" (eg. "coordinateProperties" > "times")
|
|
89
89
|
*/
|
|
90
90
|
export function coordPropsToMeta(coordProps, name, parser) {
|
|
91
|
-
return coordProps && (({props, point, id}) => {
|
|
91
|
+
return coordProps && (({props, point, id, isMulti }) => {
|
|
92
92
|
if (props) {
|
|
93
93
|
for (const key of coordProps) {
|
|
94
94
|
if (key in props) {
|
|
95
|
-
point.meta[name] = (parser || parseInt).call(this, props[key], id);
|
|
95
|
+
point.meta[name] = (parser || parseInt).call(this, (isMulti ? props[key][isMulti] : props[key]), id);
|
|
96
96
|
break;
|
|
97
97
|
}
|
|
98
98
|
}
|
|
@@ -139,9 +139,9 @@ export const iSum = (iVal, sum) => iVal + (sum || 0);
|
|
|
139
139
|
/**
|
|
140
140
|
* Alias for some leaflet core functions
|
|
141
141
|
*/
|
|
142
|
-
export const { on, off }
|
|
143
|
-
export const { throttle } = L.Util;
|
|
144
|
-
export const { hasClass }
|
|
142
|
+
export const { on, off } = L.DomEvent;
|
|
143
|
+
export const { throttle, wrapNum } = L.Util;
|
|
144
|
+
export const { hasClass } = L.DomUtil;
|
|
145
145
|
|
|
146
146
|
/**
|
|
147
147
|
* Limit floating point precision
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export function Acceleration(){const _=L.Control.Elevation.Utils;let opts=this.options,acceleration={};return acceleration.label=opts.accelerationLabel||L._(opts.imperial?"ft/s²":"m/s²"),opts.accelerationFactor=opts.accelerationFactor||1,{name:"acceleration",unit:acceleration.label,deltaMax:this.options.accelerationDeltaMax,clampRange:this.options.accelerationRange,decimals:2,pointToAttr:(_,i)=>{let dv=(this._data[i].speed-this._data[i>0?i-1:i].speed)*(1e3/opts.timeFactor),dt=(this._data[i].time-this._data[i>0?i-1:i].time)/1e3;return dt>0?Math.abs(dv/dt)*opts.accelerationFactor:0},stats:{max:_.iMax,min:_.iMin,avg:_.iAvg},scale:{axis:"y",position:"right",scale:{min:0,max:1},tickPadding:16,labelX:25,labelY:-8},path:{label:"Acceleration",yAttr:"acceleration",scaleX:"distance",scaleY:"acceleration",color:"#050402",strokeColor:"#000",strokeOpacity:"0.5",fillOpacity:"0.25"},tooltip:{chart:item=>L._("a: ")+item.acceleration+" "+acceleration.label,marker:item=>Math.round(item.acceleration)+" "+acceleration.label,order:60},summary:{minacceleration:{label:"Min Acceleration: ",value:(track,unit)=>Math.round(track.acceleration_min||0)+" "+unit,order:60},maxacceleration:{label:"Max Acceleration: ",value:(track,unit)=>Math.round(track.acceleration_max||0)+" "+unit,order:61},avgacceleration:{label:"Avg Acceleration: ",value:(track,unit)=>Math.round(track.acceleration_avg||0)+" "+unit,order:62}}}}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export function Altitude(){const _=L.Control.Elevation.Utils;let opts=this.options,altitude={},theme=opts.theme.replace("-theme",""),color=_.Colors[theme]||{};return opts.altitudeFactor=opts.imperial?this.__footFactor:opts.altitudeFactor||1,altitude.label=opts.imperial?"ft":opts.yLabel,{name:"altitude",required:this.options.slope,meta:"z",unit:altitude.label,statsName:"elevation",skipNull:this.options.skipNullZCoords,deltaMax:this.options.altitudeDeltaMax,clampRange:this.options.altitudeRange,pointToAttr:(_,i)=>this._data[i].z*opts.altitudeFactor,stats:{max:_.iMax,min:_.iMin,avg:_.iAvg},grid:{axis:"y",position:"left",scale:"y"},scale:{axis:"y",position:"left",scale:"y",labelX:-3,labelY:-8},path:{label:"Altitude",scaleX:"distance",scaleY:"altitude",className:"area",color:color.area||theme,strokeColor:opts.detached?color.stroke:"#000",strokeOpacity:"1",fillOpacity:opts.detached?color.alpha||"0.8":1,preferCanvas:opts.preferCanvas},tooltip:{name:"y",chart:item=>L._("y: ")+_.round(item[opts.yAttr],opts.decimalsY)+" "+altitude.label,marker:item=>_.round(item[opts.yAttr],opts.decimalsY)+" "+altitude.label,order:10},summary:{minele:{label:"Min Elevation: ",value:(track,unit)=>(track.elevation_min||0).toFixed(2)+" "+unit,order:30},maxele:{label:"Max Elevation: ",value:(track,unit)=>(track.elevation_max||0).toFixed(2)+" "+unit,order:31},avgele:{label:"Avg Elevation: ",value:(track,unit)=>(track.elevation_avg||0).toFixed(2)+" "+unit,order:32}}}}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export function Distance(){const _=L.Control.Elevation.Utils;let opts=this.options,distance={};return opts.distanceFactor=opts.imperial?this.__mileFactor:opts.distanceFactor||1,distance.label=opts.imperial?"mi":opts.xLabel,{name:"distance",attr:"dist",unit:distance.label,decimals:5,pointToAttr:(_,i)=>(i>0?this._data[i-1].dist:0)+this._data[i].latlng.distanceTo(this._data[i>0?i-1:i].latlng)*opts.distanceFactor/1e3,onPointAdded:(distance,i)=>this.track_info.distance=distance,scale:{axis:"x",position:"bottom",scale:"x",labelY:25,labelX:()=>this._width()+6,ticks:()=>_.clamp(this._chart._xTicks()/2,[4,1/0])},grid:{axis:"x",position:"bottom",scale:"x"},tooltip:{name:"x",chart:item=>L._("x: ")+_.round(item[opts.xAttr],opts.decimalsX)+" "+distance.label,order:20},summary:{totlen:{label:"Total Length: ",value:track=>(track.distance||0).toFixed(2)+" "+distance.label,order:10}}}}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export function Slope(){const _=L.Control.Elevation.Utils;let opts=this.options,slope={};return slope.label=opts.slopeLabel||"%",{name:"slope",meta:"slope",unit:slope.label,deltaMax:this.options.slopedDeltaMax,clampRange:this.options.slopeRange,decimals:2,pointToAttr:(_,i)=>{let dx=1e3*(this._data[i].dist-this._data[i>0?i-1:i].dist),dy=this._data[i][this.options.yAttr]-this._data[i>0?i-1:i][this.options.yAttr];return isNaN(dy)||0===dx?0:dy/dx*100},onPointAdded:(_,i)=>{let dz=this._data[i][this.options.yAttr]-this._data[i>0?i-1:i][this.options.yAttr];dz>0?this.track_info.ascent=(this.track_info.ascent||0)+dz:dz<0&&(this.track_info.descent=(this.track_info.descent||0)-dz)},stats:{max:_.iMax,min:_.iMin,avg:_.iAvg},scale:{axis:"y",position:"right",scale:{min:-1,max:1},tickPadding:16,labelX:25,labelY:-8},path:{label:"Slope",yAttr:"slope",scaleX:"distance",scaleY:"slope",color:"#F00",strokeColor:"#000",strokeOpacity:"0.5",fillOpacity:"0.25"},tooltip:{chart:item=>L._("m: ")+item.slope+slope.label,marker:item=>Math.round(item.slope)+slope.label,order:40},summary:{minslope:{label:"Min Slope: ",value:(track,unit)=>Math.round(track.slope_min||0)+" "+unit,order:40},maxslope:{label:"Max Slope: ",value:(track,unit)=>Math.round(track.slope_max||0)+" "+unit,order:41},avgslope:{label:"Avg Slope: ",value:(track,unit)=>Math.round(track.slope_avg||0)+" "+unit,order:42},ascent:{label:"Total Ascent: ",value:(track,unit)=>Math.round(track.ascent||0)+" "+(this.options.imperial?"ft":"m"),order:43},descent:{label:"Total Descent: ",value:(track,unit)=>Math.round(track.descent||0)+" "+(this.options.imperial?"ft":"m"),order:45}}}}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export function Speed(){const _=L.Control.Elevation.Utils;let opts=this.options,speed={};return speed.label=opts.speedLabel||L._(opts.imperial?"mph":"km/h"),opts.speedFactor=opts.speedFactor||1,{name:"speed",required:this.options.acceleration,unit:speed.label,deltaMax:this.options.speedDeltaMax,clampRange:this.options.speedRange,decimals:2,pointToAttr:(_,i)=>{let dx=1e3*(this._data[i].dist-this._data[i>0?i-1:i].dist),dt=this._data[i].time-this._data[i>0?i-1:i].time;return dt>0?Math.abs(dx/dt*opts.timeFactor)*opts.speedFactor:0},stats:{max:_.iMax,min:_.iMin,avg:_.iAvg},scale:this.options.speed&&"summary"!=this.options.speed&&{axis:"y",position:"right",scale:{min:0,max:1},tickPadding:16,labelX:25,labelY:-8},path:this.options.speed&&"summary"!=this.options.speed&&{label:"Speed",yAttr:"speed",scaleX:"distance",scaleY:"speed",color:"#03ffff",strokeColor:"#000",strokeOpacity:"0.5",fillOpacity:"0.25"},tooltip:this.options.speed&&{chart:item=>L._("v: ")+item.speed+" "+speed.label,marker:item=>Math.round(item.speed)+" "+speed.label,order:50},summary:this.options.speed&&{minspeed:{label:"Min Speed: ",value:(track,unit)=>Math.round(track.speed_min||0)+" "+unit,order:51},maxspeed:{label:"Max Speed: ",value:(track,unit)=>Math.round(track.speed_max||0)+" "+unit,order:51},avgspeed:{label:"Avg Speed: ",value:(track,unit)=>Math.round(track.speed_avg||0)+" "+unit,order:52}}}}
|
package/src/handlers/time.min.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export function Time(){const _=L.Control.Elevation.Utils;let opts=this.options,time={};return time.label=opts.timeLabel||"t",opts.timeFactor=opts.timeFactor||3600,this._timeAVGSpeed=(opts.timeAVGSpeed||3.6)*(opts.speedFactor||1),opts.timeFormat?"time"==opts.timeFormat?opts.timeFormat=time=>new Date(time).toLocaleTimeString():"date"==opts.timeFormat&&(opts.timeFormat=time=>new Date(time).toLocaleDateString()):opts.timeFormat=time=>new Date(time).toLocaleString().replaceAll("/","-").replaceAll(","," "),opts.xTimeFormat=opts.xTimeFormat||(t=>_.formatTime(t).split("'")[0]),{name:"time",required:this.options.speed||this.options.acceleration||this.options.timestamps,coordinateProperties:["coordTimes","times","time"],coordPropsToMeta:_.parseDate,pointToAttr:function(point,i){if(!point.meta||!point.meta.time)if(point.meta=point.meta||{},i>0){let dx=this._data[i].dist-this._data[i-1].dist,t0=this._data[i-1].time.getTime();point.meta.time=new Date(t0+dx/this._timeAVGSpeed*this.options.timeFactor*1e3)}else point.meta.time=new Date(Date.now());let time=point.meta.time.getTime()-60*point.meta.time.getTimezoneOffset()*1e3!=0?point.meta.time:0;return this._data[i].duration=i>0?(this._data[i-1].duration||0)+Math.abs(time-this._data[i-1].time):0,time},onPointAdded:(_,i)=>this.track_info.time=this._data[i].duration,scale:opts.time&&"summary"!=opts.time&&!L.Browser.mobile&&{axis:"x",position:"top",scale:{attr:"duration",min:0},label:time.label,labelY:-10,labelX:()=>this._width(),name:"time",ticks:()=>_.clamp(this._chart._xTicks()/2,[4,1/0]),tickFormat:d=>0==d?"":opts.xTimeFormat(d),onAxisMount:axis=>{axis.select(".domain").remove(),axis.selectAll("text").attr("opacity",.65).style("font-family","Monospace").style("font-size","110%"),axis.selectAll(".tick line").attr("y2",this._height()).attr("stroke-dasharray",2).attr("opacity",.75)}},tooltips:[this.options.time&&{name:"time",chart:item=>L._("T: ")+_.formatTime(item.duration||0),order:20},this.options.timestamps&&{name:"date",chart:item=>L._("t: ")+this.options.timeFormat(item.time),order:21}],summary:this.options.time&&{tottime:{label:"Total Time: ",value:track=>_.formatTime(track.time||0),order:20}}}}
|