@raruto/leaflet-elevation 1.9.5 → 2.0.1
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 +6 -5
- package/dist/leaflet-elevation.css +52 -161
- package/dist/leaflet-elevation.js +1587 -3883
- package/dist/leaflet-elevation.js.map +1 -1
- package/dist/leaflet-elevation.min.css +1 -1
- package/dist/leaflet-elevation.min.js +1 -3
- package/dist/leaflet-elevation.min.js.map +1 -1
- package/images/checkered.png +0 -0
- package/libs/leaflet-gpxgroup.js +2 -2
- package/package.json +9 -11
- package/src/{chart.js → components/chart.js} +147 -144
- package/src/{components.js → components/d3.js} +43 -71
- package/src/{marker.js → components/marker.js} +11 -14
- package/src/{summary.js → components/summary.js} +4 -5
- package/src/control.js +421 -326
- package/src/handlers/acceleration.js +64 -0
- package/src/handlers/altitude.js +76 -0
- package/src/handlers/cadence.js +54 -0
- package/src/handlers/distance.js +45 -0
- package/src/handlers/heart.js +53 -0
- package/src/handlers/slope.js +79 -0
- package/src/handlers/speed.js +66 -0
- package/src/{time.js → handlers/time.js} +32 -54
- package/src/index.css +52 -161
- package/src/index.js +0 -24
- package/src/options.js +20 -28
- package/src/utils.js +74 -102
- package/src/acceleration.js +0 -113
- package/src/altitude.js +0 -119
- package/src/distance.js +0 -69
- package/src/slope.js +0 -129
- package/src/speed.js +0 -118
package/src/control.js
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
import 'leaflet-i18n';
|
|
2
2
|
import * as _ from './utils';
|
|
3
|
-
import * as D3 from './components';
|
|
4
|
-
import { Chart } from './chart';
|
|
5
|
-
import { Marker } from './marker';
|
|
6
|
-
import { Summary } from './summary';
|
|
7
3
|
import { Options } from './options';
|
|
8
4
|
|
|
9
5
|
export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
@@ -11,19 +7,23 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
11
7
|
includes: L.Evented ? L.Evented.prototype : L.Mixin.Events,
|
|
12
8
|
|
|
13
9
|
options: Options,
|
|
14
|
-
__mileFactor: 0.621371,
|
|
15
|
-
__footFactor: 3.28084,
|
|
16
|
-
__D3:
|
|
17
|
-
__TOGEOJSON:
|
|
18
|
-
__LGEOMUTIL:
|
|
19
|
-
__LALMOSTOVER:
|
|
20
|
-
__LDISTANCEM:
|
|
10
|
+
__mileFactor: 0.621371, // 1 km = (0.621371 mi)
|
|
11
|
+
__footFactor: 3.28084, // 1 m = (3.28084 ft)
|
|
12
|
+
__D3: 'https://unpkg.com/d3@6.5.0/dist/d3.min.js',
|
|
13
|
+
__TOGEOJSON: 'https://unpkg.com/@tmcw/togeojson@4.6.0/dist/togeojson.umd.js',
|
|
14
|
+
__LGEOMUTIL: 'https://unpkg.com/leaflet-geometryutil@0.9.3/src/leaflet.geometryutil.js',
|
|
15
|
+
__LALMOSTOVER: 'https://unpkg.com/leaflet-almostover@1.0.1/src/leaflet.almostover.js',
|
|
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',
|
|
20
|
+
__modulesFolder: '../src/handlers/',
|
|
21
21
|
|
|
22
22
|
/*
|
|
23
23
|
* Add data to the diagram either from GPX or GeoJSON and update the axis domain and data
|
|
24
24
|
*/
|
|
25
25
|
addData: function(d, layer) {
|
|
26
|
-
this.
|
|
26
|
+
this.import(this.__D3)
|
|
27
27
|
.then(() => {
|
|
28
28
|
if (typeof layer === "undefined" && d.on) {
|
|
29
29
|
layer = d;
|
|
@@ -52,10 +52,11 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
52
52
|
* Reset data and display
|
|
53
53
|
*/
|
|
54
54
|
clear: function() {
|
|
55
|
-
if (this._marker)
|
|
56
|
-
if (this._chart)
|
|
57
|
-
if (this._layers)
|
|
58
|
-
if (this._markers)
|
|
55
|
+
if (this._marker) this._marker.remove();
|
|
56
|
+
if (this._chart) this._clearChart();
|
|
57
|
+
if (this._layers) this._clearLayers(this._layers);
|
|
58
|
+
if (this._markers) this._clearLayers(this._markers);
|
|
59
|
+
if (this._circleMarkers) this._clearLayers(this._circleMarkers);
|
|
59
60
|
|
|
60
61
|
this._data = [];
|
|
61
62
|
this.track_info = {};
|
|
@@ -67,7 +68,7 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
67
68
|
|
|
68
69
|
_clearChart: function() {
|
|
69
70
|
if (this._events && this._events.elechart_updated) {
|
|
70
|
-
this._events.elechart_updated.forEach(
|
|
71
|
+
this._events.elechart_updated.forEach(({fn, ctx}) => this.off('elechart_updated', fn, ctx));
|
|
71
72
|
}
|
|
72
73
|
if (this._chart && this._chart._container) {
|
|
73
74
|
this._chart._container.selectAll('g.point .point').remove();
|
|
@@ -75,17 +76,11 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
75
76
|
}
|
|
76
77
|
},
|
|
77
78
|
|
|
78
|
-
_clearLayers: function() {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
},
|
|
84
|
-
|
|
85
|
-
_clearMarkers: function() {
|
|
86
|
-
if (this._markers && this._markers.eachLayer) {
|
|
87
|
-
this._markers.eachLayer(l => l.remove())
|
|
88
|
-
this._markers.clearLayers();
|
|
79
|
+
_clearLayers: function(l) {
|
|
80
|
+
l = l || this._layers;
|
|
81
|
+
if (l && l.eachLayer) {
|
|
82
|
+
l.eachLayer(f => f.remove())
|
|
83
|
+
l.clearLayers();
|
|
89
84
|
}
|
|
90
85
|
},
|
|
91
86
|
|
|
@@ -144,8 +139,7 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
144
139
|
},
|
|
145
140
|
|
|
146
141
|
getBounds: function(data) {
|
|
147
|
-
|
|
148
|
-
return L.latLngBounds(data.map((d) => d.latlng));
|
|
142
|
+
return L.latLngBounds((data || this._data).map((d) => d.latlng));
|
|
149
143
|
},
|
|
150
144
|
|
|
151
145
|
/**
|
|
@@ -165,63 +159,54 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
165
159
|
/**
|
|
166
160
|
* Initialize chart control "options" and "container".
|
|
167
161
|
*/
|
|
168
|
-
initialize: function(
|
|
162
|
+
initialize: function(opts) {
|
|
163
|
+
|
|
164
|
+
opts = L.setOptions(this, opts);
|
|
165
|
+
|
|
169
166
|
this._data = [];
|
|
170
167
|
this._layers = L.featureGroup();
|
|
171
168
|
this._markers = L.featureGroup();
|
|
169
|
+
this._circleMarkers = L.featureGroup();
|
|
172
170
|
this._markedSegments = L.polyline([]);
|
|
173
|
-
this.
|
|
171
|
+
this._start = (opts.trkStart || Options.trkStart);
|
|
172
|
+
this._end = (opts.trkEnd || Options.trkEnd);
|
|
173
|
+
this._chartEnabled = true;
|
|
174
|
+
this._yCoordMax = -Infinity;
|
|
174
175
|
this.track_info = {};
|
|
175
|
-
this.handlers = [];
|
|
176
|
+
// this.handlers = [];
|
|
176
177
|
|
|
177
|
-
|
|
178
|
+
if (opts.followMarker) this._setMapView = _.throttle(this._setMapView, 300, this);
|
|
179
|
+
if (opts.legend) opts.margins.bottom += 30;
|
|
180
|
+
if (opts.theme) opts.polylineSegments.className += ' ' + opts.theme;
|
|
181
|
+
if (opts.wptIcons === true) opts.wptIcons = Options.wptIcons;
|
|
182
|
+
if (opts.distanceMarkers === true) opts.distanceMarkers = Options.distanceMarkers;
|
|
183
|
+
if (opts.trkStart) this._start.addTo(this._circleMarkers);
|
|
184
|
+
if (opts.trkEnd) this._end.addTo(this._circleMarkers);
|
|
178
185
|
|
|
179
|
-
if (this.options.followMarker) this._setMapView = L.Util.throttle(this._setMapView, 300, this);
|
|
180
|
-
if (this.options.legend) this.options.margins.bottom += 30;
|
|
181
|
-
if (this.options.theme) this.options.polylineSegments.className += ' ' + this.options.theme;
|
|
182
|
-
if (this.options.wptIcons === true) this.options.wptIcons = Options.wptIcons;
|
|
183
|
-
if (this.options.distanceMarkers === true) this.options.distanceMarkers = Options.distanceMarkers;
|
|
184
186
|
|
|
185
|
-
this._markedSegments.setStyle(
|
|
187
|
+
this._markedSegments.setStyle(opts.polylineSegments);
|
|
186
188
|
|
|
187
189
|
// Leaflet canvas renderer colors
|
|
188
|
-
L.extend(
|
|
190
|
+
L.extend(_.Colors, opts.colors || {});
|
|
189
191
|
|
|
190
192
|
// Various stuff
|
|
191
193
|
this._fixCanvasPaths();
|
|
192
194
|
this._fixTooltipSize();
|
|
195
|
+
|
|
193
196
|
},
|
|
194
197
|
|
|
195
198
|
/**
|
|
196
199
|
* Javascript scripts downloader (lazy loader)
|
|
197
200
|
*/
|
|
198
|
-
|
|
199
|
-
if (!this.options.lazyLoadJS) {
|
|
200
|
-
return Promise.resolve();
|
|
201
|
-
}
|
|
201
|
+
import: function(src, condition) {
|
|
202
202
|
switch(src) {
|
|
203
|
-
case this.__D3:
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
break;
|
|
207
|
-
case this.
|
|
208
|
-
loader = '_togeojsonLazyLoader';
|
|
209
|
-
condition = typeof toGeoJSON !== 'object';
|
|
210
|
-
break;
|
|
211
|
-
case this.__LGEOMUTIL:
|
|
212
|
-
loader = '_geomutilLazyLoader';
|
|
213
|
-
condition = typeof L.GeometryUtil !== 'object';
|
|
214
|
-
break;
|
|
215
|
-
case this.__LALMOSTOVER:
|
|
216
|
-
loader = '_almostoverLazyLoader';
|
|
217
|
-
condition = typeof L.Handler.AlmostOver !== 'function';
|
|
218
|
-
break;
|
|
219
|
-
case this.__LDISTANCEM:
|
|
220
|
-
loader = '_distanceMarkersLazyLoader';
|
|
221
|
-
condition = typeof L.DistanceMarkers !== 'function';
|
|
222
|
-
break;
|
|
203
|
+
case this.__D3: condition = typeof d3 !== 'object'; break;
|
|
204
|
+
case this.__TOGEOJSON: condition = typeof toGeoJSON !== 'object'; break;
|
|
205
|
+
case this.__LGEOMUTIL: condition = typeof L.GeometryUtil !== 'object'; break;
|
|
206
|
+
case this.__LALMOSTOVER: condition = typeof L.Handler.AlmostOver !== 'function'; break;
|
|
207
|
+
case this.__LDISTANCEM: condition = typeof L.DistanceMarkers !== 'function'; break;
|
|
223
208
|
}
|
|
224
|
-
return
|
|
209
|
+
return condition !== false ? import(src) : Promise.resolve();
|
|
225
210
|
},
|
|
226
211
|
|
|
227
212
|
/**
|
|
@@ -239,33 +224,23 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
239
224
|
this._map = map;
|
|
240
225
|
|
|
241
226
|
let container = this._container = _.create("div", "elevation-control elevation " + this.options.theme + " " + (this.options.detached ? '' : 'leaflet-control'));
|
|
242
|
-
|
|
243
|
-
this.lazyLoad(this.__D3)
|
|
244
|
-
.then(() => {
|
|
245
|
-
this._initButton(container);
|
|
246
|
-
this._initChart(container);
|
|
247
|
-
this._initSummary(container);
|
|
248
|
-
this._initMarker(map);
|
|
249
|
-
this._initLayer(map);
|
|
250
227
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
this._updateSummary();
|
|
268
|
-
});
|
|
228
|
+
let modules = [
|
|
229
|
+
"Distance",
|
|
230
|
+
"Time",
|
|
231
|
+
"Altitude",
|
|
232
|
+
"Slope",
|
|
233
|
+
"Speed",
|
|
234
|
+
"Acceleration",
|
|
235
|
+
...this.options.handlers
|
|
236
|
+
].filter(m => false !== this.options[typeof m == "string" && m.toLowerCase()]);
|
|
237
|
+
|
|
238
|
+
this._loadModules(modules); // Inject here required modules (data handlers)
|
|
239
|
+
this._initButton(container);
|
|
240
|
+
this._initChart(container);
|
|
241
|
+
this._initSummary(container);
|
|
242
|
+
this._initMarker(map);
|
|
243
|
+
this._initLayer(map);
|
|
269
244
|
|
|
270
245
|
return container;
|
|
271
246
|
},
|
|
@@ -278,18 +253,18 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
278
253
|
this._container = null;
|
|
279
254
|
|
|
280
255
|
map
|
|
281
|
-
.off('zoom viewreset zoomanim',
|
|
282
|
-
.off('resize',
|
|
283
|
-
.off('resize',
|
|
284
|
-
.off('mousedown',
|
|
256
|
+
.off('zoom viewreset zoomanim', this._hideMarker, this)
|
|
257
|
+
.off('resize', this._resetView, this)
|
|
258
|
+
.off('resize', this._resizeChart, this)
|
|
259
|
+
.off('mousedown', this._resetDrag, this);
|
|
285
260
|
|
|
286
|
-
_.off(map.getContainer(), 'mousewheel',
|
|
287
|
-
_.off(map.getContainer(), 'touchstart',
|
|
288
|
-
_.off(document, 'keydown',
|
|
261
|
+
_.off(map.getContainer(), 'mousewheel', this._resetDrag, this);
|
|
262
|
+
_.off(map.getContainer(), 'touchstart', this._resetDrag, this);
|
|
263
|
+
_.off(document, 'keydown', this._onKeyDown, this);
|
|
289
264
|
|
|
290
265
|
this
|
|
291
|
-
.off('eledata_added eledata_loaded',
|
|
292
|
-
.off('eledata_added eledata_loaded',
|
|
266
|
+
.off('eledata_added eledata_loaded', this._updateChart, this)
|
|
267
|
+
.off('eledata_added eledata_loaded', this._updateSummary, this);
|
|
293
268
|
},
|
|
294
269
|
|
|
295
270
|
/**
|
|
@@ -336,7 +311,7 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
336
311
|
break;
|
|
337
312
|
|
|
338
313
|
default:
|
|
339
|
-
console.warn('Unsopperted GeoJSON feature geometry type:' + geom.type);
|
|
314
|
+
return console.warn('Unsopperted GeoJSON feature geometry type:' + geom.type);
|
|
340
315
|
}
|
|
341
316
|
}
|
|
342
317
|
if (d.type === "FeatureCollection") {
|
|
@@ -357,11 +332,13 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
357
332
|
_addGeoJSONData: function(coords, properties) {
|
|
358
333
|
coords.forEach((point, i) => {
|
|
359
334
|
|
|
360
|
-
//
|
|
361
|
-
point.meta = point.meta ?? { time: null, ele: null
|
|
335
|
+
// GARMIN_EXTENSIONS = ["hr", "cad", "atemp", "wtemp", "depth", "course", "bearing"];
|
|
336
|
+
point.meta = point.meta ?? { time: null, ele: null };
|
|
362
337
|
|
|
363
338
|
// "coordinateProperties" property is generated inside "@tmcw/toGeoJSON"
|
|
364
|
-
let props
|
|
339
|
+
let props = (properties && properties.coordinateProperties) || properties;
|
|
340
|
+
|
|
341
|
+
point.prev = (attr) => (attr ? this._data[i > 0 ? i - 1 : 0][attr] : this._data[i > 0 ? i - 1 : 0]);
|
|
365
342
|
|
|
366
343
|
this.fire("elepoint_init", { point: point, props: props, id: i });
|
|
367
344
|
|
|
@@ -372,6 +349,8 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
372
349
|
);
|
|
373
350
|
|
|
374
351
|
this.fire("elepoint_added", { point: point, index: this._data.length - 1 });
|
|
352
|
+
|
|
353
|
+
if (this._yCoordMax < this._data[this._data.length - 1][this.options.yAttr]) this._yCoordMax = this._data[this._data.length - 1][this.options.yAttr];
|
|
375
354
|
});
|
|
376
355
|
|
|
377
356
|
this.fire("eletrack_added", { coords: coords, index: this._data.length - 1 });
|
|
@@ -399,7 +378,7 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
399
378
|
if (layer) this._layers.addLayer(layer)
|
|
400
379
|
// Postpone adding the distance markers (lazy: true)
|
|
401
380
|
if (layer && this.options.distanceMarkers && this.options.distanceMarkers.lazy) {
|
|
402
|
-
layer.on('add remove', (
|
|
381
|
+
layer.on('add remove', ({target, type}) => L.DistanceMarkers && target instanceof L.Polyline && target[type + 'DistanceMarkers']());
|
|
403
382
|
}
|
|
404
383
|
},
|
|
405
384
|
|
|
@@ -412,17 +391,18 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
412
391
|
*/
|
|
413
392
|
_initAlmostOverHandler: function(map, layer) {
|
|
414
393
|
if(!map || !this.options.almostOver) return;
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
.
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
}
|
|
394
|
+
Promise.all([
|
|
395
|
+
this.import(this.__LGEOMUTIL),
|
|
396
|
+
this.import(this.__LALMOSTOVER)
|
|
397
|
+
]).then(() => {
|
|
398
|
+
map.addHandler('almostOver', L.Handler.AlmostOver)
|
|
399
|
+
if (L.GeometryUtil && map.almostOver && map.almostOver.enabled()) {
|
|
400
|
+
map.almostOver.addLayer(layer);
|
|
401
|
+
map
|
|
402
|
+
.on('almost:move', (e) => this._onMouseMoveLayer(e))
|
|
403
|
+
.on('almost:out', (e) => this._onMouseOut(e));
|
|
404
|
+
}
|
|
405
|
+
});
|
|
426
406
|
},
|
|
427
407
|
|
|
428
408
|
/**
|
|
@@ -431,9 +411,10 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
431
411
|
_initDistanceMarkers: function(map, layer) {
|
|
432
412
|
if (!map) return;
|
|
433
413
|
if (this.options.distanceMarkers) {
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
.
|
|
414
|
+
Promise.all([
|
|
415
|
+
this.import(this.__LGEOMUTIL),
|
|
416
|
+
this.import(this.__LDISTANCEM)
|
|
417
|
+
]).then(() => this.options.polyline && layer.addTo(map) && this._circleMarkers.bringToFront());
|
|
437
418
|
} else if (this.options.polyline) {
|
|
438
419
|
layer.addTo(map);
|
|
439
420
|
}
|
|
@@ -459,7 +440,12 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
459
440
|
*/
|
|
460
441
|
_initMapIntegrations: function(control, layer) {
|
|
461
442
|
let map = control._map;
|
|
462
|
-
if (control.
|
|
443
|
+
if (control._data.length) {
|
|
444
|
+
control._start.setLatLng(control._data[0].latlng);
|
|
445
|
+
control._end.setLatLng(control._data[control._data.length -1].latlng);
|
|
446
|
+
}
|
|
447
|
+
if (map) {
|
|
448
|
+
control._circleMarkers.addTo(map);
|
|
463
449
|
map.once('layeradd', (e) => control.options.autofitBounds && control.fitBounds(layer.getBounds()));
|
|
464
450
|
if (!L.Browser.mobile) {
|
|
465
451
|
control._initAlmostOverHandler(map, layer);
|
|
@@ -492,12 +478,14 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
492
478
|
_fixCanvasPaths: function() {
|
|
493
479
|
let oldProto = L.Canvas.prototype._fillStroke;
|
|
494
480
|
let control = this;
|
|
481
|
+
|
|
482
|
+
let theme = this.options.theme.replace('-theme', '');
|
|
483
|
+
let color = _.Colors[theme] || {};
|
|
484
|
+
|
|
495
485
|
L.Canvas.include({
|
|
496
486
|
_fillStroke: function(ctx, layer) {
|
|
497
487
|
if (control._layers.hasLayer(layer)) {
|
|
498
488
|
|
|
499
|
-
let theme = control.options.theme.replace('-theme', '');
|
|
500
|
-
let color = D3.Colors[theme] || {};
|
|
501
489
|
let options = layer.options;
|
|
502
490
|
|
|
503
491
|
options.color = color.line || color.area || theme;
|
|
@@ -528,12 +516,12 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
528
516
|
*/
|
|
529
517
|
_fixTooltipSize: function() {
|
|
530
518
|
this.on('elechart_init', () =>
|
|
531
|
-
this.once('elechart_change elechart_hover',
|
|
519
|
+
this.once('elechart_change elechart_hover', ({data, xCoord}) => {
|
|
532
520
|
if (this._chartEnabled) {
|
|
533
|
-
this._chart._showDiagramIndicator(
|
|
534
|
-
this._chart._showDiagramIndicator(
|
|
521
|
+
this._chart._showDiagramIndicator(data, xCoord);
|
|
522
|
+
this._chart._showDiagramIndicator(data, xCoord);
|
|
535
523
|
}
|
|
536
|
-
this._updateMarker(
|
|
524
|
+
this._updateMarker(data);
|
|
537
525
|
})
|
|
538
526
|
);
|
|
539
527
|
},
|
|
@@ -560,15 +548,6 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
560
548
|
if (this._map) this._map.fire(type, data, propagate);
|
|
561
549
|
},
|
|
562
550
|
|
|
563
|
-
/**
|
|
564
|
-
* Calculates chart height.
|
|
565
|
-
*/
|
|
566
|
-
_height: function() {
|
|
567
|
-
if (this._chart) return this._chart._height();
|
|
568
|
-
let opts = this.options;
|
|
569
|
-
return opts.height - opts.margins.top - opts.margins.bottom;
|
|
570
|
-
},
|
|
571
|
-
|
|
572
551
|
/*
|
|
573
552
|
* Hides the position/height indicator marker drawn onto the map
|
|
574
553
|
*/
|
|
@@ -584,9 +563,6 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
584
563
|
_initChart: function(container) {
|
|
585
564
|
let opts = this.options;
|
|
586
565
|
|
|
587
|
-
opts.xTicks = this._xTicks();
|
|
588
|
-
opts.yTicks = this._yTicks();
|
|
589
|
-
|
|
590
566
|
if (opts.detached) {
|
|
591
567
|
let { offsetWidth, offsetHeight} = this.eleDiv;
|
|
592
568
|
if (offsetWidth > 0) opts.width = offsetWidth;
|
|
@@ -598,42 +574,66 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
598
574
|
if (opts._maxWidth > clientWidth) opts.width = clientWidth - 30;
|
|
599
575
|
}
|
|
600
576
|
|
|
601
|
-
|
|
577
|
+
Promise.all([
|
|
578
|
+
this.import(this.__D3),
|
|
579
|
+
this.import(this.__LCHART)
|
|
580
|
+
]).then((m) => {
|
|
602
581
|
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
582
|
+
let chart = this._chart = new (m[1] || Elevation).Chart(opts, this);
|
|
583
|
+
|
|
584
|
+
this._x = this._chart._x;
|
|
585
|
+
this._y = this._chart._y;
|
|
586
|
+
|
|
587
|
+
d3
|
|
588
|
+
.select(container)
|
|
589
|
+
.call(chart.render())
|
|
590
|
+
|
|
591
|
+
chart
|
|
592
|
+
.on('reset_drag', this._hideMarker, this)
|
|
593
|
+
.on('mouse_enter', this._onMouseEnter, this)
|
|
594
|
+
.on('dragged', this._onDragEnd, this)
|
|
595
|
+
.on('mouse_move', this._onMouseMove, this)
|
|
596
|
+
.on('mouse_out', this._onMouseOut, this)
|
|
597
|
+
.on('ruler_filter', this._onRulerFilter, this)
|
|
598
|
+
.on('zoom', this._updateChart, this)
|
|
599
|
+
.on('elepath_toggle', this._onToggleChart, this)
|
|
600
|
+
.on('margins_updated', this._resizeChart, this);
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
this.fire("elechart_axis");
|
|
604
|
+
|
|
605
|
+
if (this.options.legend) this.fire("elechart_legend");
|
|
606
|
+
|
|
607
|
+
this.fire("elechart_init");
|
|
609
608
|
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
.on('ruler_filter', this._rulerFilterHandler, this)
|
|
617
|
-
.on('zoom', this._updateChart, this)
|
|
618
|
-
.on('elepath_toggle', this._toggleChartHandler, this)
|
|
619
|
-
.on('margins_updated',this._resizeChart, this);
|
|
609
|
+
map
|
|
610
|
+
.on('zoom viewreset zoomanim', this._hideMarker, this)
|
|
611
|
+
.on('resize', this._resetView, this)
|
|
612
|
+
.on('resize', this._resizeChart, this)
|
|
613
|
+
.on('rotate', this._rotateMarker, this)
|
|
614
|
+
.on('mousedown', this._resetDrag, this);
|
|
620
615
|
|
|
616
|
+
_.on(map.getContainer(), 'mousewheel', this._resetDrag, this);
|
|
617
|
+
_.on(map.getContainer(), 'touchstart', this._resetDrag, this);
|
|
618
|
+
_.on(document, 'keydown', this._onKeyDown, this);
|
|
621
619
|
|
|
622
|
-
|
|
620
|
+
this
|
|
621
|
+
.on('eledata_added eledata_loaded', this._updateChart, this)
|
|
622
|
+
.on('eledata_added eledata_loaded', this._updateSummary, this);
|
|
623
623
|
|
|
624
|
-
|
|
624
|
+
this._updateChart();
|
|
625
|
+
this._updateSummary();
|
|
626
|
+
});
|
|
625
627
|
|
|
626
|
-
this.fire("elechart_init");
|
|
627
628
|
},
|
|
628
629
|
|
|
629
630
|
_initLayer: function() {
|
|
630
631
|
this._layers
|
|
631
|
-
.on('layeradd layerremove', (
|
|
632
|
-
let layer = e.layer
|
|
632
|
+
.on('layeradd layerremove', ({layer, type}) => {
|
|
633
633
|
let node = layer.getElement && layer.getElement();
|
|
634
|
-
_.toggleClass(node, this.options.polyline.className + ' ' + this.options.theme,
|
|
635
|
-
_.toggleEvent(layer, "mousemove", this.
|
|
636
|
-
_.toggleEvent(layer, "mouseout", this.
|
|
634
|
+
_.toggleClass(node, this.options.polyline.className + ' ' + this.options.theme, type == 'layeradd');
|
|
635
|
+
_.toggleEvent(layer, "mousemove", this._onMouseMoveLayer.bind(this), type == 'layeradd')
|
|
636
|
+
_.toggleEvent(layer, "mouseout", this._onMouseOut.bind(this), type == 'layeradd');
|
|
637
637
|
});
|
|
638
638
|
},
|
|
639
639
|
|
|
@@ -647,9 +647,14 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
647
647
|
|
|
648
648
|
if (this._renderer) this._renderer.remove()
|
|
649
649
|
this._renderer = L.svg({ pane: "elevationPane" }).addTo(this._map); // default leaflet svg renderer
|
|
650
|
-
this._marker = new Marker(this.options);
|
|
651
650
|
|
|
652
|
-
|
|
651
|
+
Promise.all([
|
|
652
|
+
this.import(this.__D3),
|
|
653
|
+
this.import(this.__LMARKER)
|
|
654
|
+
]).then((m) => {
|
|
655
|
+
this._marker = new (m[1] || Elevation).Marker(this.options, this);
|
|
656
|
+
this.fire("elechart_marker");
|
|
657
|
+
});
|
|
653
658
|
},
|
|
654
659
|
|
|
655
660
|
/**
|
|
@@ -684,15 +689,13 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
684
689
|
},
|
|
685
690
|
|
|
686
691
|
_initSummary: function(container) {
|
|
687
|
-
this.
|
|
688
|
-
|
|
689
|
-
d3.select(container).call(this._summary.render());
|
|
690
|
-
},
|
|
692
|
+
this.import(this.__LSUMMARY).then((m)=>{
|
|
693
|
+
this._summary = new (m || Elevation).Summary({ summary: this.options.summary }, this);
|
|
691
694
|
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
};
|
|
695
|
+
this.on('elechart_init', () => {
|
|
696
|
+
d3.select(container).call(this._summary.render());
|
|
697
|
+
});
|
|
698
|
+
});
|
|
696
699
|
},
|
|
697
700
|
|
|
698
701
|
/**
|
|
@@ -708,6 +711,31 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
708
711
|
}).catch((err) => console.warn(err));
|
|
709
712
|
},
|
|
710
713
|
|
|
714
|
+
/**
|
|
715
|
+
* Dynamically import only required javascript modules (code splitting)
|
|
716
|
+
*/
|
|
717
|
+
_loadModules: function(handlers) {
|
|
718
|
+
// First map known classnames (eg. "Altitude" --> L.Control.Elevation.Altitude)
|
|
719
|
+
handlers = handlers.map((h) => typeof h === 'string' && typeof L.Control.Elevation[h] !== "undefined" ? L.Control.Elevation[h] : h);
|
|
720
|
+
// Then load optional classes and custom imports (eg. "Cadence" --> import('../src/handlers/cadence.js'))
|
|
721
|
+
Promise.
|
|
722
|
+
all(
|
|
723
|
+
handlers
|
|
724
|
+
.filter(h => typeof h === 'string' || h instanceof Promise)
|
|
725
|
+
.map(file => file instanceof Promise ? file : this.import(this.__modulesFolder + file.toLowerCase() + '.js'))
|
|
726
|
+
)
|
|
727
|
+
.then((m) => {
|
|
728
|
+
_.each(m, (exported) => {
|
|
729
|
+
let fn = Object.keys(exported)[0];
|
|
730
|
+
if (fn && typeof L.Control.Elevation[fn] === "undefined" ) {
|
|
731
|
+
handlers[fn] = L.Control.Elevation[fn] = exported[fn];
|
|
732
|
+
|
|
733
|
+
}
|
|
734
|
+
});
|
|
735
|
+
_.each(handlers, h => this._registerHandler(h));
|
|
736
|
+
});
|
|
737
|
+
},
|
|
738
|
+
|
|
711
739
|
/**
|
|
712
740
|
* Simple GeoJSON data loader (L.GeoJSON).
|
|
713
741
|
*/
|
|
@@ -768,78 +796,78 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
768
796
|
},
|
|
769
797
|
});
|
|
770
798
|
|
|
771
|
-
control.
|
|
799
|
+
control.import(control.__D3).then(() => {
|
|
772
800
|
control._initMapIntegrations(control, layer);
|
|
773
|
-
control._fireEvt("eledata_loaded", { data: geojson, layer: layer, name: control.track_info.name, track_info: control.track_info })
|
|
801
|
+
control._fireEvt("eledata_loaded", { data: geojson, layer: layer, name: control.track_info.name, track_info: control.track_info });
|
|
774
802
|
});
|
|
775
803
|
|
|
776
804
|
return layer;
|
|
777
805
|
},
|
|
778
806
|
|
|
779
|
-
|
|
807
|
+
_onDragEnd: function({ dragstart, dragend}) {
|
|
780
808
|
this._hideMarker();
|
|
781
|
-
this.fitBounds(L.latLngBounds([
|
|
809
|
+
this.fitBounds(L.latLngBounds([dragstart.latlng, dragend.latlng]));
|
|
782
810
|
|
|
783
811
|
this.fire("elechart_dragged");
|
|
784
812
|
},
|
|
785
813
|
|
|
814
|
+
_onKeyDown: function({key}) {
|
|
815
|
+
if(!this.options.detached && key === "Escape"){
|
|
816
|
+
this._collapse()
|
|
817
|
+
};
|
|
818
|
+
},
|
|
819
|
+
|
|
786
820
|
/**
|
|
787
|
-
* Trigger mouseenter event
|
|
821
|
+
* Trigger mouseenter event.
|
|
788
822
|
*/
|
|
789
|
-
|
|
823
|
+
_onMouseEnter: function() {
|
|
790
824
|
this.fire('elechart_enter');
|
|
791
825
|
},
|
|
792
826
|
|
|
793
827
|
/*
|
|
794
828
|
* Handles the moueseover the chart and displays distance and altitude level.
|
|
795
829
|
*/
|
|
796
|
-
|
|
797
|
-
if (
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
if (item) {
|
|
803
|
-
let xCoord = e.xCoord;
|
|
830
|
+
_onMouseMove: function({xCoord}) {
|
|
831
|
+
if (this._chartEnabled && this._data.length) {
|
|
832
|
+
let item = this._findItemForX(xCoord);
|
|
833
|
+
if (item) {
|
|
834
|
+
if (this._chartEnabled) this._chart._showDiagramIndicator(item, xCoord);
|
|
804
835
|
|
|
805
|
-
|
|
836
|
+
this._updateMarker(item);
|
|
837
|
+
this._setMapView(item);
|
|
806
838
|
|
|
807
|
-
|
|
808
|
-
|
|
839
|
+
if (this._map) {
|
|
840
|
+
_.addClass(this._map.getContainer(), 'elechart-hover');
|
|
841
|
+
}
|
|
809
842
|
|
|
810
|
-
|
|
811
|
-
|
|
843
|
+
this.fire("elechart_change", { data: item, xCoord: xCoord });
|
|
844
|
+
this.fire("elechart_hover", { data: item, xCoord: xCoord });
|
|
812
845
|
}
|
|
813
|
-
|
|
814
|
-
this.fire("elechart_change", { data: item, xCoord: xCoord });
|
|
815
|
-
this.fire("elechart_hover", { data: item, xCoord: xCoord });
|
|
816
846
|
}
|
|
817
847
|
},
|
|
818
848
|
|
|
819
849
|
/*
|
|
820
850
|
* Handles mouseover events of the data layers on the map.
|
|
821
851
|
*/
|
|
822
|
-
|
|
823
|
-
if (
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
this.fire("elechart_change", { data: item, xCoord: xCoord });
|
|
852
|
+
_onMouseMoveLayer: function({latlng}) {
|
|
853
|
+
if (this._data.length) {
|
|
854
|
+
let item = this._findItemForLatLng(latlng);
|
|
855
|
+
if (item) {
|
|
856
|
+
let xCoord = item.xDiagCoord;
|
|
857
|
+
|
|
858
|
+
if (this._chartEnabled) this._chart._showDiagramIndicator(item, xCoord);
|
|
859
|
+
|
|
860
|
+
this._updateMarker(item);
|
|
861
|
+
|
|
862
|
+
this.fire("elechart_change", { data: item, xCoord: xCoord });
|
|
863
|
+
}
|
|
836
864
|
}
|
|
837
865
|
},
|
|
838
866
|
|
|
839
867
|
/*
|
|
840
868
|
* Handles the moueseout over the chart.
|
|
841
869
|
*/
|
|
842
|
-
|
|
870
|
+
_onMouseOut: function() {
|
|
843
871
|
if (!this.options.detached) {
|
|
844
872
|
this._hideMarker();
|
|
845
873
|
this._chart._hideDiagramIndicator();
|
|
@@ -852,6 +880,33 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
852
880
|
this.fire("elechart_leave");
|
|
853
881
|
},
|
|
854
882
|
|
|
883
|
+
/**
|
|
884
|
+
* Handles the drag event over the ruler filter.
|
|
885
|
+
*/
|
|
886
|
+
_onRulerFilter: function({coords}) {
|
|
887
|
+
this._updateMapSegments(coords);
|
|
888
|
+
},
|
|
889
|
+
|
|
890
|
+
/**
|
|
891
|
+
* Toggle chart data on legend click
|
|
892
|
+
*/
|
|
893
|
+
_onToggleChart: function({ name, enabled }) {
|
|
894
|
+
|
|
895
|
+
this._chartEnabled = this._chart._hasActiveLayers();
|
|
896
|
+
|
|
897
|
+
// toggle layer visibility on empty chart
|
|
898
|
+
this._layers.eachLayer(layer => _.toggleClass(layer.getElement && layer.getElement(), this.options.polyline.className + ' ' + this.options.theme, this._chartEnabled));
|
|
899
|
+
|
|
900
|
+
// toggle option value (eg. altitude = { 'disabled' || 'enabled' })
|
|
901
|
+
this.options[name] = !enabled && this.options[name] == 'disabled' ? 'enabled' : 'disabled';
|
|
902
|
+
|
|
903
|
+
// remove marker on empty chart
|
|
904
|
+
if (!this._chartEnabled) {
|
|
905
|
+
this._chart._hideDiagramIndicator();
|
|
906
|
+
this._marker.remove();
|
|
907
|
+
}
|
|
908
|
+
},
|
|
909
|
+
|
|
855
910
|
/**
|
|
856
911
|
* Simple GeoJSON Parser
|
|
857
912
|
*/
|
|
@@ -866,7 +921,7 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
866
921
|
*/
|
|
867
922
|
_parseFromString: function(data) {
|
|
868
923
|
return new Promise(resolve =>
|
|
869
|
-
this.
|
|
924
|
+
this.import(this.__TOGEOJSON).then(() => {
|
|
870
925
|
let geojson;
|
|
871
926
|
try {
|
|
872
927
|
geojson = this._parseFromXMLString(data.trim());
|
|
@@ -967,22 +1022,31 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
967
1022
|
* Base handler for iterative track statistics (dist, time, z, slope, speed, acceleration, ...)
|
|
968
1023
|
*/
|
|
969
1024
|
_registerDataAttribute: function(props) {
|
|
970
|
-
// save here a reference to last used point
|
|
971
|
-
let lastValid = null;
|
|
972
1025
|
|
|
973
1026
|
// parse of "coordinateProperties" for later usage
|
|
974
|
-
if (props.
|
|
975
|
-
this.on("elepoint_init", (e) => props.
|
|
1027
|
+
if (props.coordPropsToMeta) {
|
|
1028
|
+
this.on("elepoint_init", (e) => props.coordPropsToMeta.call(this, e));
|
|
976
1029
|
}
|
|
977
1030
|
|
|
1031
|
+
// prevent excessive variabile instanstations
|
|
1032
|
+
let i, curr, prev, attr;
|
|
1033
|
+
|
|
1034
|
+
// save here a reference to last used point
|
|
1035
|
+
let lastValid = null;
|
|
1036
|
+
|
|
978
1037
|
// iteration
|
|
979
|
-
this.on("elepoint_added", (
|
|
1038
|
+
this.on("elepoint_added", ({index, point}) => {
|
|
1039
|
+
i = index;
|
|
1040
|
+
|
|
1041
|
+
prev = curr ?? this._data[i]; // same as: this._data[i > 0 ? i - 1 : i]
|
|
1042
|
+
curr = this._data[i];
|
|
1043
|
+
attr = props.attr || props.name;
|
|
980
1044
|
|
|
981
1045
|
// check and fix missing data on last added point
|
|
982
1046
|
if (props.skipNull === false) {
|
|
983
|
-
let curr = this._data[
|
|
984
|
-
if(
|
|
985
|
-
let prev = this._data[
|
|
1047
|
+
let curr = this._data[i][attr];
|
|
1048
|
+
if(i > 0) {
|
|
1049
|
+
let prev = this._data[i - 1][attr];
|
|
986
1050
|
if (isNaN(prev)) {
|
|
987
1051
|
if (!isNaN(lastValid) && !isNaN(curr)) {
|
|
988
1052
|
prev = (lastValid + curr) / 2;
|
|
@@ -991,8 +1055,8 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
991
1055
|
} else if (!isNaN(curr)) {
|
|
992
1056
|
prev = curr;
|
|
993
1057
|
}
|
|
994
|
-
if (!isNaN(prev)) return this._data.splice(
|
|
995
|
-
this._data[
|
|
1058
|
+
if (!isNaN(prev)) return this._data.splice(i - 1, 1);
|
|
1059
|
+
this._data[i - 1][attr] = prev;
|
|
996
1060
|
}
|
|
997
1061
|
}
|
|
998
1062
|
// update reference to last used point (ie. if it has data)
|
|
@@ -1002,25 +1066,107 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
1002
1066
|
}
|
|
1003
1067
|
|
|
1004
1068
|
// retrieve point value
|
|
1005
|
-
|
|
1069
|
+
curr[attr] = props.pointToAttr.call(this, point, i);
|
|
1070
|
+
|
|
1071
|
+
// update "track_info" stats (min, max, avg, ...)
|
|
1072
|
+
if (props.stats) {
|
|
1073
|
+
for (const key in props.stats) {
|
|
1074
|
+
let sname = (props.statsName || attr) + (key != '' ? '_' : '');
|
|
1075
|
+
this.track_info[sname + key] = props.stats[key].call(this, curr[attr], this.track_info[sname + key]);
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1006
1078
|
|
|
1007
|
-
//
|
|
1008
|
-
if(props.
|
|
1079
|
+
// Limit "crazy" delta values.
|
|
1080
|
+
if (props.deltaMax) {
|
|
1081
|
+
curr[attr] =_.wrapDelta(curr[attr], prev[attr], props.deltaMax);
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
// Range of acceptable values.
|
|
1085
|
+
if (props.clampRange) {
|
|
1086
|
+
curr[attr] = _.clamp(curr[attr], props.clampRange);
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
// Limit floating point precision.
|
|
1090
|
+
if (!isNaN(props.decimals)) {
|
|
1091
|
+
curr[attr] = _.round(curr[attr], props.decimals);
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
// update here some mixins (eg. complex "track_info" stuff)
|
|
1095
|
+
if(props.onPointAdded) props.onPointAdded.call(this, curr[attr], i, point);
|
|
1009
1096
|
});
|
|
1010
1097
|
},
|
|
1098
|
+
|
|
1099
|
+
/**
|
|
1100
|
+
* Parse a module definition and attach related function listeners
|
|
1101
|
+
*/
|
|
1102
|
+
_registerHandler: function(props) {
|
|
1103
|
+
|
|
1104
|
+
// eg. L.Control.Altitude
|
|
1105
|
+
if (typeof props === "function") {
|
|
1106
|
+
return this._registerHandler(props.call(this));
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
// eg. "altitude" == true
|
|
1110
|
+
if (this.options[props.name] || props.required) {
|
|
1111
|
+
|
|
1112
|
+
this._registerDataAttribute({
|
|
1113
|
+
name: props.name,
|
|
1114
|
+
attr: props.attr,
|
|
1115
|
+
skipNull: props.skipNull,
|
|
1116
|
+
deltaMax: props.deltaMax,
|
|
1117
|
+
clampRange: props.clampRange,
|
|
1118
|
+
decimals: props.decimals,
|
|
1119
|
+
coordPropsToMeta: _.coordPropsToMeta(props.coordinateProperties, props.meta || props.name, props.coordPropsToMeta),
|
|
1120
|
+
pointToAttr: props.pointToAttr,
|
|
1121
|
+
onPointAdded: props.onPointAdded,
|
|
1122
|
+
stats: props.stats,
|
|
1123
|
+
statsName: props.statsName,
|
|
1124
|
+
});
|
|
1125
|
+
|
|
1126
|
+
if (props.grid) {
|
|
1127
|
+
props.grid.name = props.grid.name || props.name;
|
|
1128
|
+
this._registerAxisGrid(props.grid);
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
if (this.options[props.name] !== "summary") {
|
|
1132
|
+
if (props.scale) {
|
|
1133
|
+
props.scale.name = props.scale.name || props.name;
|
|
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
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
|
|
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)
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
if (props.summary) {
|
|
1156
|
+
for (const key in props.summary) {
|
|
1157
|
+
props.summary[key].unit = props.summary[key].unit || props.unit;
|
|
1158
|
+
}
|
|
1159
|
+
this._registerSummary(props.summary);
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
},
|
|
1011
1163
|
|
|
1012
1164
|
/**
|
|
1013
1165
|
* Add chart or marker tooltip info
|
|
1014
1166
|
*/
|
|
1015
1167
|
_registerTooltip: function(props) {
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
this.on("elechart_init", () => this._chart._registerTooltip(label));
|
|
1019
|
-
}
|
|
1020
|
-
if (props.marker) {
|
|
1021
|
-
let label = L.extend({}, props, { value: props.marker });
|
|
1022
|
-
this.on("elechart_marker", () => this._marker._registerTooltip(label));
|
|
1023
|
-
}
|
|
1168
|
+
props.chart && this.on("elechart_init", () => this._chart._registerTooltip(L.extend({}, props, { value: props.chart })));
|
|
1169
|
+
props.marker && this.on("elechart_marker", () => this._marker._registerTooltip(L.extend({}, props, { value: props.marker })));
|
|
1024
1170
|
},
|
|
1025
1171
|
|
|
1026
1172
|
/**
|
|
@@ -1054,85 +1200,39 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
1054
1200
|
* Hacky way for handling chart resize. Deletes it and redraw chart.
|
|
1055
1201
|
*/
|
|
1056
1202
|
_resizeChart: function() {
|
|
1057
|
-
if(
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
if (opts.detached) {
|
|
1067
|
-
newWidth = (this.eleDiv || this._container).offsetWidth;
|
|
1068
|
-
} else {
|
|
1069
|
-
let { clientWidth } = this._map.getContainer();
|
|
1070
|
-
newWidth = opts._maxWidth > clientWidth ? clientWidth - 30 : opts._maxWidth;
|
|
1071
|
-
}
|
|
1072
|
-
|
|
1073
|
-
if (newWidth) {
|
|
1074
|
-
let chart = this._chart;
|
|
1075
|
-
opts.width = newWidth;
|
|
1076
|
-
if (chart && chart._chart) {
|
|
1077
|
-
chart._chart._resize(opts);
|
|
1078
|
-
opts.xTicks = this._xTicks();
|
|
1079
|
-
opts.yTicks = this._yTicks();
|
|
1080
|
-
this._updateChart();
|
|
1203
|
+
if (this._container && _.style(this._container, "display") != "none") {
|
|
1204
|
+
let opts = this.options;
|
|
1205
|
+
let newWidth = opts.detached ? (this.eleDiv || this._container).offsetWidth : _.clamp(opts._maxWidth, [0, this._map.getContainer().clientWidth - 30]);
|
|
1206
|
+
if (newWidth) {
|
|
1207
|
+
opts.width = newWidth;
|
|
1208
|
+
if (this._chart && this._chart._chart) {
|
|
1209
|
+
this._chart._chart._resize(opts);
|
|
1210
|
+
this._updateChart();
|
|
1211
|
+
}
|
|
1081
1212
|
}
|
|
1213
|
+
this._updateMapSegments();
|
|
1082
1214
|
}
|
|
1083
|
-
|
|
1084
|
-
this._updateMapSegments();
|
|
1085
|
-
},
|
|
1086
|
-
|
|
1087
|
-
/**
|
|
1088
|
-
* Handles the drag event over the ruler filter.
|
|
1089
|
-
*/
|
|
1090
|
-
_rulerFilterHandler: function(e) {
|
|
1091
|
-
this._updateMapSegments(e.coords);
|
|
1092
1215
|
},
|
|
1093
1216
|
|
|
1094
1217
|
/**
|
|
1095
1218
|
* Collapse or Expand chart control.
|
|
1096
1219
|
*/
|
|
1097
1220
|
_toggle: function() {
|
|
1098
|
-
|
|
1099
|
-
this._collapse();
|
|
1100
|
-
else
|
|
1101
|
-
this._expand();
|
|
1221
|
+
_.hasClass(this._container, "elevation-expanded") ? this._collapse() : this._expand();
|
|
1102
1222
|
},
|
|
1103
1223
|
|
|
1104
1224
|
/**
|
|
1105
1225
|
* Update map center and zoom (followMarker: true)
|
|
1106
1226
|
*/
|
|
1107
1227
|
_setMapView: function(item) {
|
|
1108
|
-
if (
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
},
|
|
1117
|
-
|
|
1118
|
-
/**
|
|
1119
|
-
* Toggle chart data on legend click
|
|
1120
|
-
*/
|
|
1121
|
-
_toggleChartHandler: function(e) {
|
|
1122
|
-
let { name, enabled } = e;
|
|
1123
|
-
|
|
1124
|
-
this._chartEnabled = this._chart._hasActiveLayers();
|
|
1125
|
-
|
|
1126
|
-
// toggle layer visibility on empty chart
|
|
1127
|
-
this._layers.eachLayer(layer => _.toggleClass(layer.getElement && layer.getElement(), this.options.polyline.className + ' ' + this.options.theme, this._chartEnabled));
|
|
1128
|
-
|
|
1129
|
-
// toggle option value (eg. altitude = { 'disabled' || 'disabled' })
|
|
1130
|
-
this.options[name] = !enabled && this.options[name] == 'disabled' ? 'enabled' : 'disabled';
|
|
1131
|
-
|
|
1132
|
-
// remove marker on empty chart
|
|
1133
|
-
if (!this._chartEnabled) {
|
|
1134
|
-
this._chart._hideDiagramIndicator();
|
|
1135
|
-
this._marker.remove();
|
|
1228
|
+
if (this._map && this.options.followMarker) {
|
|
1229
|
+
let zoom = this._map.getZoom();
|
|
1230
|
+
let z = this.options.zFollow;
|
|
1231
|
+
if (typeof z === "number") {
|
|
1232
|
+
this._map.setView(item.latlng, (zoom < z ? z : zoom), { animate: true, duration: 0.25 });
|
|
1233
|
+
} else if (!this._map.getBounds().contains(item.latlng)) {
|
|
1234
|
+
this._map.setView(item.latlng, zoom, { animate: true, duration: 0.25 });
|
|
1235
|
+
}
|
|
1136
1236
|
}
|
|
1137
1237
|
},
|
|
1138
1238
|
|
|
@@ -1140,17 +1240,17 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
1140
1240
|
* Calculates [x, y] domain and then update chart.
|
|
1141
1241
|
*/
|
|
1142
1242
|
_updateChart: function() {
|
|
1143
|
-
if (
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1243
|
+
if (this._chart && this._container) {
|
|
1244
|
+
this.fire("elechart_axis");
|
|
1245
|
+
this.fire("elechart_area");
|
|
1246
|
+
|
|
1247
|
+
this._chart.update({ data: this._data, options: this.options });
|
|
1248
|
+
|
|
1249
|
+
this._x = this._chart._x;
|
|
1250
|
+
this._y = this._chart._y;
|
|
1251
|
+
|
|
1252
|
+
this.fire('elechart_updated');
|
|
1253
|
+
}
|
|
1154
1254
|
},
|
|
1155
1255
|
|
|
1156
1256
|
/*
|
|
@@ -1161,7 +1261,7 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
1161
1261
|
this._marker.update({
|
|
1162
1262
|
map : this._map,
|
|
1163
1263
|
item : item,
|
|
1164
|
-
|
|
1264
|
+
yCoordMax : this._yCoordMax || 0,
|
|
1165
1265
|
options : this.options
|
|
1166
1266
|
});
|
|
1167
1267
|
}
|
|
@@ -1190,6 +1290,8 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
1190
1290
|
* Update chart summary.
|
|
1191
1291
|
*/
|
|
1192
1292
|
_updateSummary: function() {
|
|
1293
|
+
if (!this._summary) return;
|
|
1294
|
+
|
|
1193
1295
|
this._summary.reset();
|
|
1194
1296
|
|
|
1195
1297
|
if (this.options.summary) {
|
|
@@ -1198,8 +1300,8 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
1198
1300
|
}
|
|
1199
1301
|
if (this.options.downloadLink && this._downloadURL) { // TODO: generate dynamically file content instead of using static file urls.
|
|
1200
1302
|
this._summary._container.innerHTML += '<span class="download"><a href="#">' + L._('Download') + '</a></span>'
|
|
1201
|
-
_.select('.download a', this._summary._container).onclick = (
|
|
1202
|
-
|
|
1303
|
+
_.select('.download a', this._summary._container).onclick = ({preventDefault}) => {
|
|
1304
|
+
preventDefault();
|
|
1203
1305
|
let event = { downloadLink: this.options.downloadLink, confirm: _.saveFile.bind(this, this._downloadURL) };
|
|
1204
1306
|
if (this.options.downloadLink == 'modal' && typeof CustomEvent === "function") {
|
|
1205
1307
|
document.dispatchEvent(new CustomEvent("eletrack_download", { detail: event }));
|
|
@@ -1217,24 +1319,17 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|
|
1217
1319
|
*/
|
|
1218
1320
|
_width: function() {
|
|
1219
1321
|
if (this._chart) return this._chart._width();
|
|
1220
|
-
|
|
1221
|
-
return
|
|
1322
|
+
const { width, margins } = this.options;
|
|
1323
|
+
return width - margins.left - margins.right;
|
|
1222
1324
|
},
|
|
1223
1325
|
|
|
1224
1326
|
/**
|
|
1225
|
-
*
|
|
1327
|
+
* Calculates chart height.
|
|
1226
1328
|
*/
|
|
1227
|
-
|
|
1228
|
-
if (this.
|
|
1229
|
-
|
|
1329
|
+
_height: function() {
|
|
1330
|
+
if (this._chart) return this._chart._height();
|
|
1331
|
+
const { height, margins } = this.options;
|
|
1332
|
+
return height - margins.top - margins.bottom;
|
|
1230
1333
|
},
|
|
1231
1334
|
|
|
1232
|
-
/**
|
|
1233
|
-
* Calculate chart yTicks
|
|
1234
|
-
*/
|
|
1235
|
-
_yTicks: function() {
|
|
1236
|
-
if (this.__yTicks) this.__yTicks = this.options.yTicks;
|
|
1237
|
-
return this.__yTicks || Math.round(this._height() / 30);
|
|
1238
|
-
}
|
|
1239
|
-
|
|
1240
1335
|
});
|