@raruto/leaflet-elevation 2.0.2 → 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.
@@ -85,6 +85,7 @@ export var Chart = L.Control.Elevation.Chart = L.Class.extend({
85
85
  this._updateScale();
86
86
  this._updateArea();
87
87
  this._updateAxis();
88
+ this._updateMargins();
88
89
  this._updateLegend();
89
90
  this._updateClipper();
90
91
 
@@ -536,80 +537,88 @@ export var Chart = L.Control.Elevation.Chart = L.Class.extend({
536
537
  },
537
538
 
538
539
  _updateLegend: function () {
539
-
540
- if (this.options.legend === false) return;
541
-
542
- const legendOpts = {
543
- width : this._width(),
544
- height : this._height(),
545
- margins: this.options.margins,
546
- };
547
-
548
- // Reset legend items
549
- this._legend.selectAll('g').remove();
550
- _.each(this._props.legendItems, (legend) => {
551
- this._legend.append("g").call(D3.LegendItem(L.extend(legendOpts, legend)));
552
- });
553
-
540
+ let xAxesB = this._axis.selectAll('.x.axis.bottom').nodes().length;
541
+
554
542
  // Get legend items
555
- let items = this._legend.selectAll('.legend-item');
543
+ let items = Object.keys(this._paths);
556
544
 
557
545
  // Calculate legend item positions
558
- let n = items.nodes().length;
546
+ let n = items.length;
559
547
  let v = Array(Math.floor(n / 2)).fill(null).map((d, i) => (i + 1) * 2 - (1 - Math.sign(n % 2)));
560
548
  let rev = v.slice().reverse().map((d) => -(d));
561
549
 
550
+ // push a fake element to handle center alignment (odd numbers)
562
551
  if (n % 2 !== 0) {
563
552
  rev.push(0);
564
553
  }
565
554
  v = rev.concat(v);
566
555
 
556
+ // Reset legend items
557
+ this._legend.selectAll('g').remove();
558
+ _.each(this._props.legendItems, (legend) => {
559
+ this._legend.append("g").call(
560
+ D3.LegendItem(L.extend({
561
+ width : this._width(),
562
+ height : this._height(),
563
+ margins: this.options.margins,
564
+ }, legend))
565
+ );
566
+ });
567
+
568
+ // Reset legend items
569
+ this._legend.append("g").call(
570
+ D3.LegendSmall({
571
+ width : this._width(),
572
+ height : this._height(),
573
+ items : items,
574
+ onClick: (selected) => {
575
+ _.each(items, name => this._togglePath(name, selected == name, true));
576
+ this._updateArea();
577
+ }
578
+ })
579
+ );
580
+
581
+ _.each(items, (name, i) => {
582
+ // Adjust legend item positions
583
+ this._legend.select('[data-name=' + name + ']').attr("transform", "translate(" + (v[i] * 55) + ", " + (xAxesB * 2) + ")");
584
+ // Set initial state (disabled controls)
585
+ this._togglePath(name, !(name in this.options && this.options[name] == 'disabled'), true);
586
+ });
587
+
588
+ },
589
+
590
+ _updateMargins: function() {
567
591
  // Get chart margins
568
592
  let xAxesB = this._axis.selectAll('.x.axis.bottom').nodes().length;
569
- let marginB = 30 + (xAxesB * 2);
570
- let marginR = n * 30;
593
+ let xAxesL = this._axis.selectAll('.y.axis.left').nodes().length;
594
+ let xAxesR = this._axis.selectAll('.y.axis.right').nodes().length;
595
+ let marginB = 60 + (xAxesB * 2);
596
+ let marginL = 10 + (xAxesL * 30);
597
+ let marginR = 40 + (xAxesR * 30);
598
+
599
+ let marginsUpdated = false
571
600
 
572
- // Adjust chart right margins
573
- if (n && this.options.margins.right < marginR) {
601
+ // Adjust right margin
602
+ if (xAxesR && this.options.margins.right < marginR) {
574
603
  this.options.margins.right = marginR;
575
- this.fire('margins_updated');
604
+ marginsUpdated = true;
576
605
  }
577
606
 
578
- // Adjust chart bottom margins
607
+ // Adjust left margin
608
+ if(xAxesL && this.options.margins.left < marginL) {
609
+ this.options.margins.left = marginL;
610
+ marginsUpdated = true;
611
+ }
612
+
613
+ // Adjust bottom margin
579
614
  if(xAxesB && this.options.margins.bottom < marginB) {
580
615
  this.options.margins.bottom = marginB;
581
- this.fire('margins_updated');
616
+ marginsUpdated = true;
582
617
  }
583
618
 
584
- items
585
- .each((d, i, n) => {
586
-
587
- let legend = d3.select(n[i]);
588
- let rect = legend.select('rect');
589
- let name = legend.attr('data-name');
590
- let path = this._paths[name];
591
-
592
- let tx = v[i] * 55;
593
- let ty = xAxesB * 2;
594
-
595
- legend
596
-
597
- // Adjust legend item positions
598
- .attr("transform", "translate(" + tx + ", " + ty + ")");
599
-
600
- // Set initial state (disabled controls)
601
- if (name in this.options && this.options[name] == 'disabled') {
602
- path.classed('leaflet-hidden', true);
603
- legend.select('text').style('text-decoration-line', 'line-through');
604
- legend.select('rect').style('fill-opacity', '0');
605
- }
606
-
607
- // Apply d3-zoom (bind <clipPath> mask)
608
- if (this._mask) {
609
- path.attr('mask', 'url(#' + this._mask.attr('id') + ')');
610
- }
611
-
612
- });
619
+ if (marginsUpdated) {
620
+ this.fire('margins_updated');
621
+ }
613
622
  },
614
623
 
615
624
  _updateScale: function() {
@@ -733,6 +742,21 @@ export var Chart = L.Control.Elevation.Chart = L.Class.extend({
733
742
  }));
734
743
  },
735
744
 
745
+ _togglePath(name, enabled = true, lazy = false) {
746
+ let path = this._paths[name];
747
+ let legend = this._container.select('.legend [data-name=' + name + ']');
748
+ path.classed('leaflet-hidden', !enabled);
749
+ legend.select('text').style('text-decoration-line', enabled ? '' : 'line-through');
750
+ legend.select('rect').style('fill-opacity', enabled ? '': '0');
751
+ // Apply d3-zoom (bind <clipPath> mask)
752
+ if (this._mask) {
753
+ path.attr('mask', 'url(#' + this._mask.attr('id') + ')');
754
+ }
755
+ if (!lazy) {
756
+ this._updateArea();
757
+ }
758
+ },
759
+
736
760
  _hideDiagramIndicator: function() {
737
761
  this._tooltip.attr("display", 'none');
738
762
  },
@@ -214,6 +214,70 @@ export const LegendItem = ({
214
214
  }
215
215
  };
216
216
 
217
+ export const LegendSmall = ({
218
+ width,
219
+ height,
220
+ items,
221
+ onClick
222
+ }) => {
223
+ return g => {
224
+ let idx = 0;
225
+
226
+ g.data([{
227
+ x: width,
228
+ y: height + 40
229
+ }]).attr("transform", d => "translate(" + d.x + "," + d.y + ")").classed('legend-switcher');
230
+
231
+ // let label = g.selectAll(".legend-switcher-label") .data([{ idx: 0 }]);
232
+ let label = g.append('svg:text')
233
+ .attr("class", "legend-switcher-label")
234
+ .attr("text-anchor", "end")
235
+ .attr("x", -25)
236
+ .attr("y", 5)
237
+ .on("mousedown", (e, d) => setIdx(L.Util.wrapNum((idx + 1), [0, items.length])));
238
+
239
+ let symbol = g.selectAll(".legend-switcher-symbol").data([
240
+ { type: d3.symbolTriangle, x: 0, y: 3, angle: 0, size: 50, id: "down" },
241
+ { type: d3.symbolTriangle, x: -13, y: 0, angle: 180, size: 50, id: "up" }
242
+ ]);
243
+
244
+ symbol.exit().remove();
245
+ label.exit().remove();
246
+
247
+ symbol.enter()
248
+ .append("svg:path")
249
+ .attr("class", "legend-switcher-symbol")
250
+ .attr("cursor", 'pointer')
251
+ .attr("fill", "#000")
252
+ .merge(symbol)
253
+ .attr("d",
254
+ d3.symbol()
255
+ .type(d => d.type)
256
+ .size(d => d.size)
257
+ )
258
+ .attr("transform", d => "translate(" + d.x + "," + d.y + ") rotate(" + d.angle + ")")
259
+ .on("mousedown", (e, d) => setIdx(L.Util.wrapNum((d.id === "up" ? idx + 1 : idx - 1), [0, items.length])));
260
+
261
+ const setIdx = (id) => {
262
+ idx = id;
263
+ // label.enter()
264
+ // .append('text')
265
+ // .attr("class", "legend-switcher-label")
266
+ // .attr("text-anchor", "end")
267
+ // .attr("x", -25)
268
+ // .attr("y", 5)
269
+ // .merge(label.data([{ idx: id }]))
270
+ // .text(d => items.length ? (items[idx][0].toUpperCase() + items[idx].slice(1)) : '')
271
+ // .on("mousedown", (e, d) => setIdx(L.Util.wrapNum((idx + 1), [0, items.length])));
272
+ label.text(items.length ? (items[idx][0].toUpperCase() + items[idx].slice(1)) : '');
273
+ onClick(items[idx]);
274
+ };
275
+ setIdx(0);
276
+
277
+ return g;
278
+ };
279
+ };
280
+
217
281
  export const Tooltip = ({
218
282
  xCoord,
219
283
  yCoord,
@@ -300,27 +364,21 @@ export const Ruler = ({
300
364
  return g => {
301
365
 
302
366
  g.data([{
303
- "x": 0,
304
- "y": height,
367
+ x: 0,
368
+ y: height,
305
369
  }])
306
370
  .attr("transform", d => "translate(" + d.x + "," + d.y + ")");
307
371
 
308
- let rect = g.selectAll('.horizontal-drag-rect')
309
- .data([{ w: width }]);
310
-
311
- let line = g.selectAll('.horizontal-drag-line')
312
- .data([{ w: width }]);
313
-
314
- let label = g.selectAll('.horizontal-drag-label')
315
- .data([{ w: width - 8 }]);
316
-
372
+ let rect = g.selectAll('.horizontal-drag-rect').data([{ w: width }]);
373
+ let line = g.selectAll('.horizontal-drag-line').data([{ w: width }]);
374
+ let label = g.selectAll('.horizontal-drag-label').data([{ w: width - 8 }]);
317
375
  let symbol = g.selectAll('.horizontal-drag-symbol')
318
376
  .data([{
319
- "type": d3.symbolTriangle,
320
- "x": width + 7,
321
- "y": 0,
322
- "angle": -90,
323
- "size": 50
377
+ type: d3.symbolTriangle,
378
+ x: width + 7,
379
+ y: 0,
380
+ angle: -90,
381
+ size: 50
324
382
  }]);
325
383
 
326
384
  rect.exit().remove();
package/src/control.js CHANGED
@@ -593,10 +593,6 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
593
593
  .on('margins_updated', this._resizeChart, this);
594
594
 
595
595
 
596
- this.fire("elechart_axis");
597
-
598
- if (this.options.legend) this.fire("elechart_legend");
599
-
600
596
  this.fire("elechart_init");
601
597
 
602
598
  map
@@ -1205,7 +1201,6 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
1205
1201
  _updateChart: function() {
1206
1202
  if (this._chart && this._container) {
1207
1203
  this.fire("elechart_axis");
1208
- this.fire("elechart_area");
1209
1204
 
1210
1205
  this._chart.update({ data: this._data, options: this.options });
1211
1206
 
@@ -1253,27 +1248,26 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
1253
1248
  * Update chart summary.
1254
1249
  */
1255
1250
  _updateSummary: function() {
1256
- if (!this._summary) return;
1257
-
1258
- this._summary.reset();
1259
-
1260
- if (this.options.summary) {
1261
- this.fire("elechart_summary");
1262
- this._summary.update();
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
+ }
1263
1270
  }
1264
- if (this.options.downloadLink && this._downloadURL) { // TODO: generate dynamically file content instead of using static file urls.
1265
- this._summary._container.innerHTML += '<span class="download"><a href="#">' + L._('Download') + '</a></span>'
1266
- _.select('.download a', this._summary._container).onclick = ({preventDefault}) => {
1267
- preventDefault();
1268
- let event = { downloadLink: this.options.downloadLink, confirm: _.saveFile.bind(this, this._downloadURL) };
1269
- if (this.options.downloadLink == 'modal' && typeof CustomEvent === "function") {
1270
- document.dispatchEvent(new CustomEvent("eletrack_download", { detail: event }));
1271
- } else if (this.options.downloadLink == 'link' || this.options.downloadLink === true) {
1272
- event.confirm();
1273
- }
1274
- this.fire('eletrack_download', event);
1275
- };
1276
- };
1277
1271
  },
1278
1272
 
1279
1273
 
@@ -13,8 +13,8 @@ export function Heart() {
13
13
  axis : "y",
14
14
  position : "left",
15
15
  scale : { min: -1, max: +1 },
16
- tickPadding: 16,
17
- labelX : -18,
16
+ tickPadding: 25,
17
+ labelX : -30,
18
18
  labelY : -8,
19
19
  },
20
20
  path: {
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;
package/src/utils.js CHANGED
@@ -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 } = L.DomEvent;
143
- export const { throttle } = L.Util;
144
- export const { hasClass } = L.DomUtil;
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