@raruto/leaflet-elevation 2.3.4 → 2.5.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.
@@ -0,0 +1,45 @@
1
+ /**
2
+ * @see https://github.com/Raruto/leaflet-elevation/issues/211
3
+ *
4
+ * @example
5
+ * ```js
6
+ * L.control.Elevation({ handlers: [ 'Labels' ], labelsRotation: 25, labelsAlign: 'start' })
7
+ * ```
8
+ */
9
+ export function Labels() {
10
+
11
+ this.on('elechart_updated', function(e) {
12
+
13
+ const pointG = this._chart._chart.pane('point');
14
+
15
+ const textRotation = this.options.labelsRotation ?? -90;
16
+ const textAnchor = this.options.labelsAlign;
17
+
18
+ if (90 == Math.abs(textRotation)) {
19
+
20
+ pointG.selectAll('text')
21
+ .attr('dy', '4px')
22
+ .attr("dx", (d, i, el) => Math.sign(textRotation) * (this._height() - d3.select(el[i].parentElement).datum().y - 8) + 'px')
23
+ .attr('text-anchor', textRotation > 0 ? 'end' : 'start')
24
+ .attr('transform', 'rotate(' + textRotation + ')')
25
+
26
+ pointG.selectAll('circle')
27
+ .attr('r', '2.5')
28
+ .attr('fill', '#fff')
29
+ .attr("stroke", '#000')
30
+ .attr("stroke-width", '1.1');
31
+
32
+ } else if (!isNaN(textRotation)) {
33
+
34
+ pointG.selectAll('text')
35
+ .attr("dx", "4px")
36
+ .attr("dy", "-9px")
37
+ .attr('text-anchor', textAnchor ?? (0 == textRotation ? 'start' : 'middle'))
38
+ .attr('transform', 'rotate('+ -textRotation +')')
39
+
40
+ }
41
+
42
+ });
43
+
44
+ return { };
45
+ }
@@ -0,0 +1,122 @@
1
+ /**
2
+ * @see https://github.com/Raruto/leaflet-elevation/issues/251
3
+ *
4
+ * @example
5
+ * ```js
6
+ * L.control.Elevation({
7
+ * altitude: true,
8
+ * distance: true,
9
+ * handlers: [ 'Altitude', 'Distance', 'LinearGradient', ],
10
+ * linearGradient: {
11
+ * attr: 'z',
12
+ * path: 'altitude',
13
+ * range: { 0.0: '#008800', 0.5: '#ffff00', 1.0: '#ff0000' },
14
+ * min: 'elevation_min',
15
+ * max: 'elevation_max',
16
+ * },
17
+ * })
18
+ * ```
19
+ */
20
+ export function LinearGradient() {
21
+
22
+ if (!this.options.linearGradient) {
23
+ return {};
24
+ }
25
+
26
+ const _ = L.Control.Elevation.Utils;
27
+
28
+ /**
29
+ * Initialize gradient color palette.
30
+ */
31
+ const get_palette = function ({range, min, max, depth = 256}) {
32
+ const canvas = document.createElement('canvas'),
33
+ ctx = canvas.getContext('2d'),
34
+ gradient = ctx.createLinearGradient(0, 0, 0, depth);
35
+
36
+ canvas.width = 1;
37
+ canvas.height = depth;
38
+
39
+ for (let i in range) {
40
+ gradient.addColorStop(i, range[i]);
41
+ }
42
+
43
+ ctx.fillStyle = gradient;
44
+ ctx.fillRect(0, 0, 1, depth);
45
+
46
+ const { data } = ctx.getImageData(0, 0, 1, depth);
47
+
48
+ return {
49
+ /**
50
+ * Gets the RGB values of a given z value of the current palette.
51
+ *
52
+ * @param {number} value - Value to get the color for, should be between min and max.
53
+ * @returns {string} The RGB values as `rgb(r, g, b)` string
54
+ */
55
+ getRGBColor(value) {
56
+ const idx = Math.floor(Math.min(Math.max((value - min) / (max - min), 0), 0.999) * depth) * 4;
57
+ return 'rgb(' + [data[idx], data[idx + 1], data[idx + 2]].join(',') + ')';
58
+ }
59
+ };
60
+ };
61
+
62
+ const { preferCanvas } = this.options;
63
+ const { attr, path: path_name, range, min, max } = L.extend({
64
+ attr: 'z',
65
+ path: 'altitude',
66
+ range: { 0.0: '#008800', 0.5: '#ffff00', 1.0: '#ff0000' },
67
+ min: 'elevation_min',
68
+ max: 'elevation_max',
69
+ }, (true === this.options.linearGradient) ? {} : this.options.linearGradient);
70
+
71
+ const gradient_id = path_name + '-gradient-' + _.randomId();
72
+ const legend_id = 'legend-' + gradient_id;
73
+
74
+ // Charte profile gradient
75
+ this.on('elechart_axis', () => {
76
+ if (!this._data.length) return;
77
+
78
+ const chart = this._chart;
79
+ const path = chart._paths[path_name];
80
+ const { defs } = chart._chart.utils;
81
+
82
+ const palette = get_palette({
83
+ min: isFinite(this.track_info[min]) ? this.track_info[min] : 0,
84
+ max: isFinite(this.track_info[max]) ? this.track_info[max] : 1,
85
+ range,
86
+ });
87
+
88
+ let gradient;
89
+
90
+ if (preferCanvas) {
91
+ /** ref: `path.__fillStyle` within L.Control.Elevation.Utils::drawCanvas(ctx, path) */
92
+ path.__fillStyle = gradient = chart._context.createLinearGradient(0, 0, chart._width(), 0);
93
+ } else {
94
+ defs.select('#' + gradient_id).remove();
95
+ gradient = defs.append('svg:linearGradient').attr('id', gradient_id);
96
+ gradient.addColorStop = function(offset, color) { gradient.append('svg:stop').attr('offset', offset).attr('stop-color', color) };
97
+ path.attr('fill', 'url(#' + gradient_id + ')').classed('area', false);
98
+ }
99
+
100
+ // Generate gradient for each segment picking colors from palette
101
+ for (let i = 0, data = this._data; i < data.length; i++) {
102
+ gradient.addColorStop((i) / data.length, palette.getRGBColor(data[i][attr]));
103
+ }
104
+
105
+ });
106
+
107
+ // Legend item gradient
108
+ this.on('elechart_updated', () => {
109
+ const chart = this._chart;
110
+ const { defs } = chart._chart.utils;
111
+ defs.select('#' + legend_id).remove();
112
+ const legendGradient = defs.append('svg:linearGradient').attr('id', legend_id);
113
+ Object.keys(range).sort().forEach(i => legendGradient.append('svg:stop').attr('offset', i).attr('stop-color', range[i]));
114
+
115
+ chart._container
116
+ .select('.legend-' + path_name + ' > rect')
117
+ .attr('fill', 'url(#' + legend_id + ')')
118
+ .classed('area', false);
119
+ });
120
+
121
+ return { };
122
+ }
@@ -0,0 +1,109 @@
1
+ /**
2
+ * @see https://github.com/Igor-Vladyka/leaflet.motion
3
+ *
4
+ * @example
5
+ * ```js
6
+ * L.control.Elevation({ handlers: [ 'Runner' ], runnerOptions: { polyline: {..}, motion: {..}, marker {..} } })
7
+ * ```
8
+ */
9
+ export async function Runner() {
10
+
11
+ await this.import(this.__LMOTION || 'https://unpkg.com/leaflet.motion@0.3.2/dist/leaflet.motion.min.js', typeof L.Motion !== 'object')
12
+
13
+ let { runnerOptions } = this.options;
14
+
15
+ runnerOptions = L.extend(
16
+ { polyline: {}, motion: {}, marker: undefined },
17
+ 'object' === typeof runnerOptions ? runnerOptions : {}
18
+ );
19
+
20
+ // Custom tooltips
21
+ this._registerTooltip({
22
+ name: 'here',
23
+ marker: (item) => L._("You are here: "),
24
+ order: 1,
25
+ });
26
+
27
+ this._registerTooltip({
28
+ name: 'distance',
29
+ marker: (item) => Math.round(item.dist) + " " + this.options.xLabel,
30
+ order: 2,
31
+ });
32
+
33
+ this.addCheckpoint = function (checkpoint) {
34
+ return this._registerCheckPoint({ // <-- NB these are private functions use them at your own risk!
35
+ latlng: this._findItemForX(this._x(checkpoint.dist)).latlng,
36
+ label: checkpoint.label || ''
37
+ });
38
+ }
39
+
40
+ this.addRunner = function (runner) {
41
+ let x = this._x(runner.dist);
42
+ let y = this._y(this._findItemForX(x).z)
43
+ let g = d3.select(this._container)
44
+ .select('svg > g')
45
+ .append("svg:circle")
46
+ .attr("class", "runner " + this.options.theme + " height-focus circle-lower")
47
+ .attr("r", 6)
48
+ .attr("cx", x)
49
+ .attr("cy", y);
50
+ return g;
51
+ }
52
+
53
+ this.setPositionFromLatLng = function (latlng) {
54
+ this._onMouseMoveLayer({ latlng: latlng }); // Update map and chart "markers" from latlng
55
+ };
56
+
57
+ this.tick = function (runner, dist = 0, inc = 0.1) {
58
+ dist = (dist <= this.track_info.distance - inc) ? dist + inc : 0;
59
+ this.updateRunnerPos(runner, dist);
60
+ setTimeout(() => this.tick(runner, dist), 150);
61
+ };
62
+
63
+ this.updateRunnerPos = function (runner, pos) {
64
+ let curr, x;
65
+
66
+ if (pos instanceof L.LatLng) {
67
+ curr = this._findItemForLatLng(pos);
68
+ x = this._x(curr.dist);
69
+ } else {
70
+ x = this._x(pos);
71
+ curr = this._findItemForX(x);
72
+ }
73
+
74
+ runner
75
+ .attr("cx", x)
76
+ .attr("cy", this._y(curr.z));
77
+ this.setPositionFromLatLng(curr.latlng);
78
+ };
79
+
80
+ this.animate = function (layer, speed = 1500) {
81
+
82
+ if (this._runner) {
83
+ this._runner.remove();
84
+ }
85
+
86
+ layer.setStyle({ opacity: 0.5 });
87
+
88
+ const geo = L.geoJson(layer.toGeoJSON(), { coordsToLatLng: (coords) => L.latLng(coords[0], coords[1], coords[2] * (this.options.altitudeFactor || 1)) });
89
+ this._runner = L.motion.polyline(
90
+ geo.toGeoJSON().features[0].geometry.coordinates,
91
+ L.extend({}, { color: 'red', pane: 'elevationPane', attribution: '' }, runnerOptions.polyline),
92
+ L.extend({}, { auto: true, speed: speed, }, runnerOptions.motion),
93
+ runnerOptions.marker || undefined
94
+ );
95
+
96
+ // Override default function behavior: `L.Motion.Polyline::_drawMarker()`
97
+ this._runner._drawMarker = new Proxy(this._runner._drawMarker, {
98
+ apply: (target, thisArg, argArray) => {
99
+ thisArg._runner = thisArg._runner || this.addRunner({ dist: 0 });
100
+ this.updateRunnerPos(thisArg._runner, argArray[0]);
101
+ return target.apply(thisArg, argArray);
102
+ }
103
+ });
104
+
105
+ this._runner.addTo(this._map);
106
+ };
107
+
108
+ return {};
109
+ }
@@ -1,103 +1,103 @@
1
- export function Time() {
2
-
3
- const _ = L.Control.Elevation.Utils;
4
-
5
- let opts = this.options;
6
- let time = {};
7
-
8
- time.label = opts.timeLabel || 't';
9
- opts.timeFactor = opts.timeFactor || 3600;
10
-
11
- /**
12
- * Common AVG speeds:
13
- * ----------------------
14
- * slow walk = 1.8 km/h
15
- * walking = 3.6 km/h <-- default: 3.6
16
- * running = 10.8 km/h
17
- * cycling = 18 km/h
18
- * driving = 72 km/h
19
- * ----------------------
20
- */
21
- this._timeAVGSpeed = (opts.timeAVGSpeed || 3.6) * (opts.speedFactor || 1);
22
-
23
- if (!opts.timeFormat) {
24
- opts.timeFormat = (time) => (new Date(time)).toLocaleString().replaceAll('/', '-').replaceAll(',', ' ');
25
- } else if (opts.timeFormat == 'time') {
26
- opts.timeFormat = (time) => (new Date(time)).toLocaleTimeString();
27
- } else if (opts.timeFormat == 'date') {
28
- opts.timeFormat = (time) => (new Date(time)).toLocaleDateString();
29
- }
30
-
31
- opts.xTimeFormat = opts.xTimeFormat || ((t) => _.formatTime(t).split("'")[0]);
32
-
33
- return {
34
- name: 'time',
35
- required: (this.options.speed || this.options.acceleration || this.options.timestamps),
36
- coordinateProperties: ["coordTimes", "times", "time"],
37
- coordPropsToMeta: _.parseDate,
38
- pointToAttr: function(point, i) {
39
- // Add missing timestamps (see: options.timeAVGSpeed)
40
- if (!point.meta || !point.meta.time) {
41
- point.meta = point.meta || {};
42
- if(i > 0) {
43
- let dx = (this._data[i].dist - this._data[i - 1].dist);
44
- let t0 = this._data[i - 1].time.getTime();
45
- point.meta.time = new Date(t0 + ( dx / this._timeAVGSpeed) * this.options.timeFactor * 1000);
46
- } else {
47
- point.meta.time = new Date(Date.now())
48
- }
49
- }
50
- // Handle timezone offset
51
- let time = (point.meta.time.getTime() - point.meta.time.getTimezoneOffset() * 60 * 1000 !== 0) ? point.meta.time : 0;
52
- // Update duration
53
- this._data[i].duration = i > 0 ? (this._data[i - 1].duration || 0) + Math.abs(time - this._data[i - 1].time) : 0;
54
- return time;
55
- },
56
- onPointAdded: (_, i) => this.track_info.time = this._data[i].duration,
57
- scale: (opts.time && opts.time != "summary" && !L.Browser.mobile) && {
58
- axis : "x",
59
- position : "top",
60
- scale : {
61
- attr : "duration",
62
- min : 0,
63
- },
64
- label : time.label,
65
- labelY : -10,
66
- labelX : () => this._width(),
67
- name : "time",
68
- ticks : () => _.clamp(this._chart._xTicks() / 2, [4, +Infinity]),
69
- tickFormat : (d) => (d == 0 ? '' : opts.xTimeFormat(d)),
70
- onAxisMount: axis => {
71
- axis.select(".domain")
72
- .remove();
73
- axis.selectAll("text")
74
- .attr('opacity', 0.65)
75
- .style('font-family', 'Monospace')
76
- .style('font-size', '110%');
77
- axis.selectAll(".tick line")
78
- .attr('y2', this._height())
79
- .attr('stroke-dasharray', 2)
80
- .attr('opacity', 0.75);
81
- }
82
- },
83
- tooltips: [
84
- (this.options.time) && {
85
- name: 'time',
86
- chart: (item) => L._("T: ") + _.formatTime(item.duration || 0),
87
- order: 20
88
- },
89
- (this.options.timestamps) && {
90
- name: 'date',
91
- chart: (item) => L._("t: ") + this.options.timeFormat(item.time),
92
- order: 21,
93
- }
94
- ],
95
- summary: (this.options.time) && {
96
- "tottime" : {
97
- label: "Total Time: ",
98
- value: (track) => _.formatTime(track.time || 0),
99
- order: 20
100
- }
101
- }
102
- };
1
+ export function Time() {
2
+
3
+ const _ = L.Control.Elevation.Utils;
4
+
5
+ let opts = this.options;
6
+ let time = {};
7
+
8
+ time.label = opts.timeLabel || 't';
9
+ opts.timeFactor = opts.timeFactor || 3600;
10
+
11
+ /**
12
+ * Common AVG speeds:
13
+ * ----------------------
14
+ * slow walk = 1.8 km/h
15
+ * walking = 3.6 km/h <-- default: 3.6
16
+ * running = 10.8 km/h
17
+ * cycling = 18 km/h
18
+ * driving = 72 km/h
19
+ * ----------------------
20
+ */
21
+ this._timeAVGSpeed = (opts.timeAVGSpeed || 3.6) * (opts.speedFactor || 1);
22
+
23
+ if (!opts.timeFormat) {
24
+ opts.timeFormat = (time) => (new Date(time)).toLocaleString().replaceAll('/', '-').replaceAll(',', ' ');
25
+ } else if (opts.timeFormat == 'time') {
26
+ opts.timeFormat = (time) => (new Date(time)).toLocaleTimeString();
27
+ } else if (opts.timeFormat == 'date') {
28
+ opts.timeFormat = (time) => (new Date(time)).toLocaleDateString();
29
+ }
30
+
31
+ opts.xTimeFormat = opts.xTimeFormat || ((t) => _.formatTime(t).split("'")[0]);
32
+
33
+ return {
34
+ name: 'time',
35
+ required: (this.options.speed || this.options.acceleration || this.options.timestamps),
36
+ coordinateProperties: ["coordTimes", "times", "time"],
37
+ coordPropsToMeta: _.parseDate,
38
+ pointToAttr: function(point, i) {
39
+ // Add missing timestamps (see: options.timeAVGSpeed)
40
+ if (!point.meta || !point.meta.time) {
41
+ point.meta = point.meta || {};
42
+ if (i > 0) {
43
+ let dx = (this._data[i].dist - this._data[i - 1].dist);
44
+ let t0 = this._data[i - 1].time.getTime();
45
+ point.meta.time = new Date(t0 + ( dx / this._timeAVGSpeed) * this.options.timeFactor * 1000);
46
+ } else {
47
+ point.meta.time = new Date(Date.now())
48
+ }
49
+ }
50
+ // Handle timezone offset
51
+ let time = (point.meta.time.getTime() - point.meta.time.getTimezoneOffset() * 60 * 1000 !== 0) ? point.meta.time : 0;
52
+ // Update duration
53
+ this._data[i].duration = i > 0 ? (this._data[i - 1].duration || 0) + Math.abs(time - this._data[i - 1].time) : 0;
54
+ return time;
55
+ },
56
+ onPointAdded: (_, i) => this.track_info.time = this._data[i].duration,
57
+ scale: (opts.time && opts.time != "summary" && !L.Browser.mobile) && {
58
+ axis : "x",
59
+ position : "top",
60
+ scale : {
61
+ attr : "duration",
62
+ min : 0,
63
+ },
64
+ label : time.label,
65
+ labelY : -10,
66
+ labelX : () => this._width(),
67
+ name : "time",
68
+ ticks : () => _.clamp(this._chart._xTicks() / 2, [4, +Infinity]),
69
+ tickFormat : (d) => (d == 0 ? '' : opts.xTimeFormat(d)),
70
+ onAxisMount: axis => {
71
+ axis.select(".domain")
72
+ .remove();
73
+ axis.selectAll("text")
74
+ .attr('opacity', 0.65)
75
+ .style('font-family', 'Monospace')
76
+ .style('font-size', '110%');
77
+ axis.selectAll(".tick line")
78
+ .attr('y2', this._height())
79
+ .attr('stroke-dasharray', 2)
80
+ .attr('opacity', 0.75);
81
+ }
82
+ },
83
+ tooltips: [
84
+ (this.options.time) && {
85
+ name: 'time',
86
+ chart: (item) => L._("T: ") + _.formatTime(item.duration || 0),
87
+ order: 20
88
+ },
89
+ (this.options.timestamps) && {
90
+ name: 'date',
91
+ chart: (item) => L._("t: ") + this.options.timeFormat(item.time),
92
+ order: 21,
93
+ }
94
+ ],
95
+ summary: (this.options.time) && {
96
+ "tottime" : {
97
+ label: "Total Time: ",
98
+ value: (track) => _.formatTime(track.time || 0),
99
+ order: 20
100
+ }
101
+ }
102
+ };
103
103
  }
package/src/options.js CHANGED
@@ -1,88 +1,88 @@
1
- import * as _ from './utils';
2
-
3
- export var Options = {
4
- autofitBounds: true,
5
- autohide: false,
6
- autohideMarker: true,
7
- almostover: true,
8
- altitude: true,
9
- closeBtn: true,
10
- collapsed: false,
11
- detached: true,
12
- distance: true,
13
- distanceMarkers: { lazy: true, distance: true, direction: true },
14
- dragging: !L.Browser.mobile,
15
- downloadLink: 'link',
16
- elevationDiv: "#elevation-div",
17
- edgeScale: { bar: true, icon: false, coords: false },
18
- followMarker: true,
19
- imperial: false,
20
- legend: true,
21
- handlers: ["Distance", "Time", "Altitude", "Slope", "Speed", "Acceleration"],
22
- hotline: 'elevation',
23
- marker: 'elevation-line',
24
- markerIcon: L.divIcon({
25
- className: 'elevation-position-marker',
26
- html: '<i class="elevation-position-icon"></i>',
27
- iconSize: [32, 32],
28
- iconAnchor: [16, 16],
29
- }),
30
- position: "topright",
31
- polyline: {
32
- className: 'elevation-polyline',
33
- color: '#000',
34
- opacity: 0.75,
35
- weight: 5,
36
- lineCap: 'round'
37
- },
38
- polylineSegments: {
39
- className: 'elevation-polyline-segments',
40
- color: '#F00',
41
- interactive: false,
42
- },
43
- preferCanvas: false,
44
- reverseCoords: false,
45
- ruler: true,
46
- theme: "lightblue-theme",
47
- summary: 'inline',
48
- slope: false,
49
- speed: false,
50
- time: true,
51
- timeFactor: 3600,
52
- timestamps: false,
53
- trkStart: { className: 'start-marker', radius: 6, weight: 2, color: '#fff', fillColor: '#00d800', fillOpacity: 1, interactive: false },
54
- trkEnd: { className: 'end-marker', radius: 6, weight: 2, color: '#fff', fillColor: '#ff0606', fillOpacity: 1, interactive: false },
55
- waypoints: true,
56
- wptIcons: {
57
- '': L.divIcon({
58
- className: 'elevation-waypoint-marker',
59
- html: '<i class="elevation-waypoint-icon default"></i>',
60
- iconSize: [30, 30],
61
- iconAnchor: [8, 30],
62
- }),
63
- },
64
- wptLabels: true,
65
- xAttr: "dist",
66
- xLabel: "km",
67
- yAttr: "z",
68
- yLabel: "m",
69
- zFollow: false,
70
- zooming: !L.Browser.Mobile,
71
-
72
- // Quite uncommon and undocumented options
73
- margins: { top: 30, right: 30, bottom: 30, left: 40 },
74
- height: (screen.height * 0.3) || 200,
75
- width: (screen.width * 0.6) || 600,
76
- xTicks: undefined,
77
- yTicks: undefined,
78
-
79
- decimalsX: 2,
80
- decimalsY: 0,
81
- forceAxisBounds: false,
82
- interpolation: "curveLinear",
83
- yAxisMax: undefined,
84
- yAxisMin: undefined,
85
-
86
- // Prevent CORS issues for relative locations (dynamic import)
87
- srcFolder: ((document.currentScript && document.currentScript.src) || (import.meta && import.meta.url)).split("/").slice(0,-1).join("/") + '/',
88
- };
1
+ import * as _ from './utils';
2
+
3
+ export var Options = {
4
+ autofitBounds: true,
5
+ autohide: false,
6
+ autohideMarker: true,
7
+ almostover: true,
8
+ altitude: true,
9
+ closeBtn: true,
10
+ collapsed: false,
11
+ detached: true,
12
+ distance: true,
13
+ distanceMarkers: { lazy: true, distance: true, direction: true },
14
+ dragging: !L.Browser.mobile,
15
+ downloadLink: 'link',
16
+ elevationDiv: "#elevation-div",
17
+ edgeScale: { bar: true, icon: false, coords: false },
18
+ followMarker: true,
19
+ imperial: false,
20
+ legend: true,
21
+ handlers: ["Distance", "Time", "Altitude", "Slope", "Speed", "Acceleration"],
22
+ hotline: 'elevation',
23
+ marker: 'elevation-line',
24
+ markerIcon: L.divIcon({
25
+ className: 'elevation-position-marker',
26
+ html: '<i class="elevation-position-icon"></i>',
27
+ iconSize: [32, 32],
28
+ iconAnchor: [16, 16],
29
+ }),
30
+ position: "topright",
31
+ polyline: {
32
+ className: 'elevation-polyline',
33
+ color: '#000',
34
+ opacity: 0.75,
35
+ weight: 5,
36
+ lineCap: 'round'
37
+ },
38
+ polylineSegments: {
39
+ className: 'elevation-polyline-segments',
40
+ color: '#F00',
41
+ interactive: false,
42
+ },
43
+ preferCanvas: false,
44
+ reverseCoords: false,
45
+ ruler: true,
46
+ theme: "lightblue-theme",
47
+ summary: 'inline',
48
+ slope: false,
49
+ speed: false,
50
+ time: true,
51
+ timeFactor: 3600,
52
+ timestamps: false,
53
+ trkStart: { className: 'start-marker', radius: 6, weight: 2, color: '#fff', fillColor: '#00d800', fillOpacity: 1, interactive: false },
54
+ trkEnd: { className: 'end-marker', radius: 6, weight: 2, color: '#fff', fillColor: '#ff0606', fillOpacity: 1, interactive: false },
55
+ waypoints: true,
56
+ wptIcons: {
57
+ '': L.divIcon({
58
+ className: 'elevation-waypoint-marker',
59
+ html: '<i class="elevation-waypoint-icon default"></i>',
60
+ iconSize: [30, 30],
61
+ iconAnchor: [8, 30],
62
+ }),
63
+ },
64
+ wptLabels: true,
65
+ xAttr: "dist",
66
+ xLabel: "km",
67
+ yAttr: "z",
68
+ yLabel: "m",
69
+ zFollow: false,
70
+ zooming: !L.Browser.Mobile,
71
+
72
+ // Quite uncommon and undocumented options
73
+ margins: { top: 30, right: 30, bottom: 30, left: 40 },
74
+ height: (screen.height * 0.3) || 200,
75
+ width: (screen.width * 0.6) || 600,
76
+ xTicks: undefined,
77
+ yTicks: undefined,
78
+
79
+ decimalsX: 2,
80
+ decimalsY: 0,
81
+ forceAxisBounds: false,
82
+ interpolation: "curveLinear",
83
+ yAxisMax: undefined,
84
+ yAxisMin: undefined,
85
+
86
+ // Prevent CORS issues for relative locations (dynamic import)
87
+ srcFolder: ((document.currentScript && document.currentScript.src) || (import.meta && import.meta.url)).split("/").slice(0,-1).join("/") + '/',
88
+ };