@raruto/leaflet-elevation 1.7.4 → 1.8.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.
- package/README.md +19 -2
- package/dist/leaflet-elevation.js +637 -847
- package/dist/leaflet-elevation.js.map +1 -1
- package/dist/leaflet-elevation.min.js +3 -1
- package/dist/leaflet-elevation.min.js.map +1 -1
- package/package.json +1 -1
- package/src/acceleration.js +11 -21
- package/src/altitude.js +21 -22
- package/src/chart.js +55 -175
- package/src/components.js +159 -111
- package/src/control.js +115 -209
- package/src/distance.js +15 -13
- package/src/index.js +12 -1
- package/src/marker.js +38 -98
- package/src/options.js +1 -8
- package/src/slope.js +9 -18
- package/src/speed.js +11 -21
- package/src/time.js +15 -10
- package/src/utils.js +113 -137
package/src/marker.js
CHANGED
|
@@ -7,39 +7,28 @@ export var Marker = L.Class.extend({
|
|
|
7
7
|
initialize: function(options) {
|
|
8
8
|
this.options = options;
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
switch(this.options.marker) {
|
|
11
|
+
case 'elevation-line':
|
|
12
|
+
// this._container = d3.create("g").attr("class", "height-focus-group");
|
|
13
|
+
this._container = d3.select(map.getPane('elevationPane')).select("svg > g")
|
|
14
|
+
.attr("class", "height-focus-group");
|
|
15
|
+
break;
|
|
16
|
+
case 'position-marker':
|
|
17
|
+
// this._marker = L.circleMarker([0, 0], { pane: 'overlayPane', radius: 6, fillColor: '#fff', fillOpacity:1, color: '#000', weight:1, interactive: false });
|
|
18
|
+
this._marker = L.marker([0, 0], { icon: this.options.markerIcon, zIndexOffset: 1000000, interactive: false });
|
|
19
|
+
break;
|
|
16
20
|
}
|
|
17
21
|
|
|
18
|
-
|
|
19
|
-
// this._container = d3.create("g").attr("class", "height-focus-group");
|
|
20
|
-
this._focusline = d3.create('svg:line');
|
|
21
|
-
this._focusmarker = d3.create("svg:circle");
|
|
22
|
-
this._focuslabel = d3.create("svg:text");
|
|
23
|
-
} else if (this.options.marker == 'position-marker') {
|
|
24
|
-
// this._marker = L.circleMarker([0, 0], { pane: 'overlayPane', radius: 6, fillColor: '#fff', fillOpacity:1, color: '#000', weight:1, interactive: false });
|
|
25
|
-
this._marker = L.marker([0, 0], { icon: this.options.markerIcon, zIndexOffset: 1000000, interactive: false });
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
this._focuslabels = {};
|
|
22
|
+
this._labels = {};
|
|
29
23
|
|
|
30
24
|
return this;
|
|
31
25
|
},
|
|
32
26
|
|
|
33
27
|
addTo: function(map) {
|
|
34
28
|
this._map = map;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
g.append(() => this._focusline.node());
|
|
39
|
-
g.append(() => this._focusmarker.node());
|
|
40
|
-
g.append(() => this._focuslabel.node());
|
|
41
|
-
} else if (this.options.marker == 'position-marker') {
|
|
42
|
-
this._marker.addTo(map, { pane: 'overlayPane' });
|
|
29
|
+
switch(this.options.marker) {
|
|
30
|
+
case 'elevation-line': this._container.call(D3.PositionMarker({})); break;
|
|
31
|
+
case 'position-marker': this._marker.addTo(map, { pane: 'overlayPane' }); break;
|
|
43
32
|
}
|
|
44
33
|
return this;
|
|
45
34
|
},
|
|
@@ -56,75 +45,27 @@ export var Marker = L.Class.extend({
|
|
|
56
45
|
if (props.options) this.options = props.options;
|
|
57
46
|
if (!this._map) this.addTo(props.map);
|
|
58
47
|
|
|
59
|
-
let opts = this.options;
|
|
60
|
-
let map = this._map;
|
|
61
|
-
|
|
62
48
|
this._latlng = props.item.latlng;
|
|
63
49
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
xCoord: point.x,
|
|
84
|
-
yCoord: point.y,
|
|
85
|
-
}));
|
|
86
|
-
|
|
87
|
-
this._focusline
|
|
88
|
-
.call(
|
|
89
|
-
D3.HeightFocusLine({
|
|
90
|
-
theme : opts.theme,
|
|
91
|
-
xCoord: point.x,
|
|
92
|
-
yCoord: point.y,
|
|
93
|
-
length: normalizedY
|
|
94
|
-
})
|
|
95
|
-
);
|
|
96
|
-
this._focuslabel
|
|
97
|
-
.call(
|
|
98
|
-
D3.HeightFocusLabel({
|
|
99
|
-
theme : opts.theme,
|
|
100
|
-
xCoord: point.x,
|
|
101
|
-
yCoord: normalizedY,
|
|
102
|
-
label : d3.format("." + opts.decimalsY + "f")(point[opts.yAttr]) + " " + this._yLabel
|
|
103
|
-
})
|
|
104
|
-
);
|
|
105
|
-
|
|
106
|
-
let labels = this._focuslabels;
|
|
107
|
-
let tooltip = this._focuslabel;
|
|
108
|
-
let label;
|
|
109
|
-
|
|
110
|
-
for (var i in labels) {
|
|
111
|
-
label = tooltip.select(".height-focus-" + labels[i].name);
|
|
112
|
-
|
|
113
|
-
if (!label.size()) {
|
|
114
|
-
label = tooltip.append("svg:tspan")
|
|
115
|
-
.attr("class", "height-focus-" + labels[i].name)
|
|
116
|
-
.attr("dy", "1.5em");
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
label.text(typeof labels[i].value !== "function" ? labels[i].value : labels[i].value(props.item) );
|
|
120
|
-
|
|
121
|
-
this._focuslabel.select('.height-focus-y')
|
|
122
|
-
.attr("dy", "-1.5em");
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
} else if (this.options.marker == 'position-marker') {
|
|
126
|
-
_.removeClass(this._marker.getElement(), 'leaflet-hidden');
|
|
127
|
-
this._marker.setLatLng(this._latlng);
|
|
50
|
+
switch(this.options.marker) {
|
|
51
|
+
case 'elevation-line':
|
|
52
|
+
let point = this._map.latLngToLayerPoint(this._latlng);
|
|
53
|
+
point = L.extend({}, props.item, this._map._rotate ? this._map.rotatedPointToMapPanePoint(point) : point);
|
|
54
|
+
|
|
55
|
+
this._container.classed("leaflet-hidden", false);
|
|
56
|
+
this._container.call(D3.PositionMarker({
|
|
57
|
+
theme : this.options.theme,
|
|
58
|
+
xCoord: point.x,
|
|
59
|
+
yCoord: point.y,
|
|
60
|
+
length: point.y - (this._height() / props.maxElevation * point.z), // normalized Y
|
|
61
|
+
labels: this._labels,
|
|
62
|
+
item: point
|
|
63
|
+
}));
|
|
64
|
+
break;
|
|
65
|
+
case 'position-marker':
|
|
66
|
+
_.removeClass(this._marker.getElement(), 'leaflet-hidden');
|
|
67
|
+
this._marker.setLatLng(this._latlng);
|
|
68
|
+
break;
|
|
128
69
|
}
|
|
129
70
|
},
|
|
130
71
|
|
|
@@ -133,10 +74,9 @@ export var Marker = L.Class.extend({
|
|
|
133
74
|
*/
|
|
134
75
|
remove: function() {
|
|
135
76
|
this._props = null;
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
_.addClass(this._marker.getElement(), 'leaflet-hidden');
|
|
77
|
+
switch(this.options.marker) {
|
|
78
|
+
case 'elevation-line': this._container && this._container.classed("leaflet-hidden", true); break;
|
|
79
|
+
case 'position-marker': _.addClass(this._marker.getElement(), 'leaflet-hidden'); break;
|
|
140
80
|
}
|
|
141
81
|
},
|
|
142
82
|
|
|
@@ -152,8 +92,8 @@ export var Marker = L.Class.extend({
|
|
|
152
92
|
return opts.height - opts.margins.top - opts.margins.bottom;
|
|
153
93
|
},
|
|
154
94
|
|
|
155
|
-
|
|
156
|
-
this.
|
|
95
|
+
_registerTooltip: function(props) {
|
|
96
|
+
this._labels[props.name] = props;
|
|
157
97
|
}
|
|
158
98
|
|
|
159
99
|
});
|
package/src/options.js
CHANGED
|
@@ -9,7 +9,6 @@ export var Options = {
|
|
|
9
9
|
collapsed: false,
|
|
10
10
|
detached: true,
|
|
11
11
|
distance: true,
|
|
12
|
-
distanceFactor: 1,
|
|
13
12
|
distanceMarkers: false,
|
|
14
13
|
decimalsX: 2,
|
|
15
14
|
decimalsY: 0,
|
|
@@ -19,15 +18,10 @@ export var Options = {
|
|
|
19
18
|
followMarker: true,
|
|
20
19
|
forceAxisBounds: false,
|
|
21
20
|
height: 200,
|
|
22
|
-
heightFactor: 1,
|
|
23
21
|
imperial: false,
|
|
24
22
|
interpolation: "curveLinear",
|
|
25
23
|
lazyLoadJS: true,
|
|
26
24
|
legend: true,
|
|
27
|
-
loadData: {
|
|
28
|
-
defer: false,
|
|
29
|
-
lazy: false,
|
|
30
|
-
},
|
|
31
25
|
margins: {
|
|
32
26
|
top: 30,
|
|
33
27
|
right: 30,
|
|
@@ -41,7 +35,6 @@ export var Options = {
|
|
|
41
35
|
iconSize: [32, 32],
|
|
42
36
|
iconAnchor: [16, 16],
|
|
43
37
|
}),
|
|
44
|
-
placeholder: false,
|
|
45
38
|
position: "topright",
|
|
46
39
|
polyline: {
|
|
47
40
|
className: 'elevation-polyline',
|
|
@@ -60,7 +53,6 @@ export var Options = {
|
|
|
60
53
|
ruler: true,
|
|
61
54
|
skipNullZCoords: false,
|
|
62
55
|
theme: "lightblue-theme",
|
|
63
|
-
responsive: true,
|
|
64
56
|
summary: 'inline',
|
|
65
57
|
slope: false,
|
|
66
58
|
speed: false,
|
|
@@ -68,6 +60,7 @@ export var Options = {
|
|
|
68
60
|
time: false,
|
|
69
61
|
timeFactor: 3600,
|
|
70
62
|
timeFormat: false,
|
|
63
|
+
timestamps: false,
|
|
71
64
|
sDeltaMax: undefined,
|
|
72
65
|
sInterpolation: "curveStepAfter",
|
|
73
66
|
sRange: undefined,
|
package/src/slope.js
CHANGED
|
@@ -74,39 +74,30 @@ Elevation.addInitHook(function() {
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
// Range of acceptable slope values.
|
|
77
|
-
|
|
78
|
-
let range = this.options.sRange;
|
|
79
|
-
if (slope < range[0]) slope = range[0];
|
|
80
|
-
else if (slope > range[1]) slope = range[1];
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
slope = L.Util.formatNum(slope, 2);
|
|
84
|
-
|
|
85
|
-
if (slope > sMax) sMax = slope;
|
|
86
|
-
if (slope < sMin) sMin = slope;
|
|
87
|
-
|
|
88
|
-
data[i].slope = slope;
|
|
77
|
+
slope = _.clamp(slope, this.options.sRange);
|
|
89
78
|
|
|
90
79
|
track.ascent = tAsc;
|
|
91
80
|
track.descent = tDes;
|
|
92
|
-
track.slope_max = sMax;
|
|
93
|
-
track.slope_min = sMin;
|
|
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);
|
|
94
85
|
});
|
|
95
86
|
|
|
96
|
-
this.
|
|
87
|
+
this._registerTooltip({
|
|
97
88
|
name: 'slope',
|
|
98
|
-
chart: (item) => item.slope + slope.label,
|
|
89
|
+
chart: (item) => L._("m: ") + item.slope + slope.label,
|
|
99
90
|
marker: (item) => Math.round(item.slope) + slope.label
|
|
100
91
|
});
|
|
101
92
|
|
|
102
93
|
this._registerSummary({
|
|
103
94
|
"ascent" : {
|
|
104
95
|
label: "Total Ascent: ",
|
|
105
|
-
value: (track) => Math.round(track.ascent || 0) + ' ' + this.
|
|
96
|
+
value: (track) => Math.round(track.ascent || 0) + ' ' + (this.options.imperial ? 'ft' : 'm')
|
|
106
97
|
},
|
|
107
98
|
"descent" : {
|
|
108
99
|
label: "Total Descent: ",
|
|
109
|
-
value: (track) => Math.round(track.descent || 0) + ' ' + this.
|
|
100
|
+
value: (track) => Math.round(track.descent || 0) + ' ' + (this.options.imperial ? 'ft' : 'm')
|
|
110
101
|
},
|
|
111
102
|
"minslope": {
|
|
112
103
|
label: "Min Slope: ",
|
package/src/speed.js
CHANGED
|
@@ -10,8 +10,8 @@ Elevation.addInitHook(function() {
|
|
|
10
10
|
let opts = this.options;
|
|
11
11
|
let speed = {};
|
|
12
12
|
|
|
13
|
-
speed.label
|
|
14
|
-
|
|
13
|
+
speed.label = opts.speedLabel || L._(opts.imperial ? 'mph' : 'km/h');
|
|
14
|
+
opts.speedFactor = opts.speedFactor || 1;
|
|
15
15
|
|
|
16
16
|
if (this.options.speed && this.options.speed != "summary") {
|
|
17
17
|
|
|
@@ -60,7 +60,7 @@ Elevation.addInitHook(function() {
|
|
|
60
60
|
|
|
61
61
|
if (deltaT > 0) {
|
|
62
62
|
let delta = (data[i].dist - data[i > 0 ? i - 1 : i].dist) * 1000;
|
|
63
|
-
speed = Math.abs((delta / deltaT) *
|
|
63
|
+
speed = Math.abs((delta / deltaT) * opts.timeFactor) * opts.speedFactor;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
// Try to smooth "crazy" speed values.
|
|
@@ -73,31 +73,21 @@ Elevation.addInitHook(function() {
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
// Range of acceptable speed values.
|
|
76
|
-
|
|
77
|
-
let range = this.options.speedRange;
|
|
78
|
-
if (speed < range[0]) speed = range[0];
|
|
79
|
-
else if (speed > range[1]) speed = range[1];
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
speed = L.Util.formatNum(speed, 2);
|
|
83
|
-
|
|
84
|
-
sMax = speed > sMax ? speed : sMax;
|
|
85
|
-
sMin = speed < sMin ? speed : sMin;
|
|
86
|
-
sAvg = (speed + sAvg) / 2.0;
|
|
76
|
+
speed = _.clamp(speed, this.options.speedRange);
|
|
87
77
|
|
|
88
|
-
|
|
78
|
+
track.speed_max = speed > sMax ? speed : sMax;
|
|
79
|
+
track.speed_min = speed < sMin ? speed : sMin;
|
|
80
|
+
track.speed_avg = (speed + sAvg) / 2.0;
|
|
89
81
|
|
|
90
|
-
|
|
91
|
-
track.speed_min = sMin;
|
|
92
|
-
track.speed_avg = sAvg;
|
|
82
|
+
data[i].speed = L.Util.formatNum(speed, 2);
|
|
93
83
|
});
|
|
94
84
|
|
|
95
85
|
if (this.options.speed) {
|
|
96
86
|
|
|
97
|
-
this.
|
|
87
|
+
this._registerTooltip({
|
|
98
88
|
name: 'speed',
|
|
99
|
-
chart: (item) => item.speed + " " + speed.label,
|
|
100
|
-
marker: (item) => Math.round(item.speed) + " " + speed.label
|
|
89
|
+
chart: (item) => L._('v: ') + item.speed + " " + speed.label,
|
|
90
|
+
marker: (item) => Math.round(item.speed) + " " + speed.label,
|
|
101
91
|
});
|
|
102
92
|
|
|
103
93
|
this._registerSummary({
|
package/src/time.js
CHANGED
|
@@ -8,8 +8,8 @@ Elevation.addInitHook(function() {
|
|
|
8
8
|
let opts = this.options;
|
|
9
9
|
let time = {};
|
|
10
10
|
|
|
11
|
-
time.label
|
|
12
|
-
|
|
11
|
+
time.label = opts.timeLabel || 't';
|
|
12
|
+
opts.timeFactor = opts.timeFactor || 3600;
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Common AVG speeds:
|
|
@@ -75,7 +75,7 @@ Elevation.addInitHook(function() {
|
|
|
75
75
|
e.point.meta.time = new Date(
|
|
76
76
|
(
|
|
77
77
|
i > 0
|
|
78
|
-
? data[i - 1].time.getTime() + ((( delta / speed) *
|
|
78
|
+
? data[i - 1].time.getTime() + ((( delta / speed) * opts.timeFactor) * 1000)
|
|
79
79
|
: Date.now()
|
|
80
80
|
)
|
|
81
81
|
);
|
|
@@ -94,26 +94,31 @@ Elevation.addInitHook(function() {
|
|
|
94
94
|
let deltaT = Math.abs(currT - prevT);
|
|
95
95
|
let duration = (this.track_info.time || 0) + deltaT;
|
|
96
96
|
|
|
97
|
+
this.track_info.time = duration;
|
|
98
|
+
|
|
97
99
|
data[i].time = time;
|
|
98
100
|
data[i].duration = duration;
|
|
99
|
-
|
|
100
|
-
this.track_info.time = duration;
|
|
101
101
|
});
|
|
102
102
|
|
|
103
|
-
if (this.options.time) {
|
|
104
103
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
104
|
+
if (this.options.timestamps) {
|
|
105
|
+
this._registerTooltip({
|
|
106
|
+
name: 'date',
|
|
107
|
+
chart: (item) => L._("t: ") + this.options.timeFormat(item.time)
|
|
108
108
|
});
|
|
109
|
+
}
|
|
109
110
|
|
|
111
|
+
if (this.options.time) {
|
|
112
|
+
this._registerTooltip({
|
|
113
|
+
name: 'time',
|
|
114
|
+
chart: (item) => L._("T: ") + _.formatTime(item.duration || 0)
|
|
115
|
+
});
|
|
110
116
|
this._registerSummary({
|
|
111
117
|
"tottime" : {
|
|
112
118
|
label: "Total Time: ",
|
|
113
119
|
value: (track) => _.formatTime(track.time || 0)
|
|
114
120
|
}
|
|
115
121
|
});
|
|
116
|
-
|
|
117
122
|
}
|
|
118
123
|
|
|
119
124
|
});
|