@raruto/leaflet-elevation 2.0.0 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -143,102 +143,107 @@ L.DistanceMarkers = L.LayerGroup.extend({
143
143
  // Get line coords as an array
144
144
  let coords = typeof line.getLatLngs == 'function' ? line.getLatLngs() : line;
145
145
 
146
- // Get accumulated line lengths as well as overall length
147
- let accumulated = L.GeometryUtil.accumulatedLengths(line);
148
- let length = accumulated.length > 0 ? accumulated[accumulated.length - 1] : 0;
149
-
150
- // count = Number of distance markers to be added
151
- // j = Position in accumulated line length array
152
- for (let i = 1, count = Math.floor(length / options.offset), j = 0; i <= count; ++i) {
153
-
154
- let distance = options.offset * i;
155
-
156
- // Find the first accumulated distance that is greater than the distance of this marker
157
- while (j < accumulated.length - 1 && accumulated[j] < distance) ++j;
158
-
159
- // Grab two nearest points either side marker position
160
- let p1 = coords[j - 1];
161
- let p2 = coords[j];
162
- let m_line = L.polyline([p1, p2]);
163
-
164
- // and create a simple line to interpolate on
165
- let ratio = (distance - accumulated[j - 1]) / (accumulated[j] - accumulated[j - 1]);
166
- let position = L.GeometryUtil.interpolateOnLine(map, m_line, ratio);
167
- let delta = map.project(p2).subtract(map.project(p1));
168
- let angle = Math.atan2(delta.y, delta.x);
169
-
170
- // Generate distance marker label
171
- let text = options.textFunction.call(this, distance, i, options.offset);
172
-
173
- // Grouping layer of visible layers at zoom level (arrow + distance)
174
- let zoom = this._minimumZoomLevelForItem(i, showAll);
175
- let markers = this._zoomLayers[zoom] = this._zoomLayers[zoom] || L.layerGroup()
176
-
177
- // create arrow markers
178
- if (options.direction && ((options.distance && i % 2 == 1) || !options.distance)) {
179
- if (preferCanvas) {
180
- markers.addLayer(
181
- new L.DistanceMarker(p1, {
182
- radius: 0,
183
- icon: {
184
- url: options.arrowUrl, //image link
185
- size: options.arrowSize, //image size ( default [40, 40] )
186
- rotate: 0, //image base rotate ( default 0 )
187
- offset: { x: 0, y: 0 }, //image offset ( default { x: 0, y: 0 } )
188
- },
189
- rotation: angle,
190
- interactive: false,
191
- // label: '⮞', //'➜',
192
- // font: 'normal 20pt "Helvetica Neue", Arial, Helvetica, sans-serif',
193
- // fillStyle: 'white',//'#3366CC',
194
- // strokeStyle: 'black',
195
- })
196
- );
197
- } else {
198
- markers.addLayer(
199
- L.marker(position.latLng, {
200
- icon: L.icon({
201
- iconUrl: options.arrowUrl,
202
- iconSize: options.arrowSize,
203
- }),
204
- // NB the following option is added by "leaflet-rotate"
205
- rotation: angle * L.DomUtil.RAD_TO_DEG,
206
- interactive: false,
207
- })
208
- );
146
+ // Handle "MultiLineString" features
147
+ coords = L.LineUtil.isFlat(coords) ? [coords] : coords;
148
+
149
+ coords.forEach(latlngs => {
150
+ // Get accumulated line lengths as well as overall length
151
+ let accumulated = L.GeometryUtil.accumulatedLengths(latlngs);
152
+ let length = accumulated.length > 0 ? accumulated[accumulated.length - 1] : 0;
153
+
154
+ // count = Number of distance markers to be added
155
+ // j = Position in accumulated line length array
156
+ for (let i = 1, count = Math.floor(length / options.offset), j = 0; i <= count; ++i) {
157
+
158
+ let distance = options.offset * i;
159
+
160
+ // Find the first accumulated distance that is greater than the distance of this marker
161
+ while (j < accumulated.length - 1 && accumulated[j] < distance) ++j;
162
+
163
+ // Grab two nearest points either side marker position
164
+ let p1 = latlngs[j - 1];
165
+ let p2 = latlngs[j];
166
+ let m_line = L.polyline([p1, p2]);
167
+
168
+ // and create a simple line to interpolate on
169
+ let ratio = (distance - accumulated[j - 1]) / (accumulated[j] - accumulated[j - 1]);
170
+ let position = L.GeometryUtil.interpolateOnLine(map, m_line, ratio);
171
+ let delta = map.project(p2).subtract(map.project(p1));
172
+ let angle = Math.atan2(delta.y, delta.x);
173
+
174
+ // Generate distance marker label
175
+ let text = options.textFunction.call(this, distance, i, options.offset);
176
+
177
+ // Grouping layer of visible layers at zoom level (arrow + distance)
178
+ let zoom = this._minimumZoomLevelForItem(i, showAll);
179
+ let markers = this._zoomLayers[zoom] = this._zoomLayers[zoom] || L.layerGroup()
180
+
181
+ // create arrow markers
182
+ if (options.direction && ((options.distance && i % 2 == 1) || !options.distance)) {
183
+ if (preferCanvas) {
184
+ markers.addLayer(
185
+ new L.DistanceMarker(p1, {
186
+ radius: 0,
187
+ icon: {
188
+ url: options.arrowUrl, //image link
189
+ size: options.arrowSize, //image size ( default [40, 40] )
190
+ rotate: 0, //image base rotate ( default 0 )
191
+ offset: { x: 0, y: 0 }, //image offset ( default { x: 0, y: 0 } )
192
+ },
193
+ rotation: angle,
194
+ interactive: false,
195
+ // label: '⮞', //'➜',
196
+ // font: 'normal 20pt "Helvetica Neue", Arial, Helvetica, sans-serif',
197
+ // fillStyle: 'white',//'#3366CC',
198
+ // strokeStyle: 'black',
199
+ })
200
+ );
201
+ } else {
202
+ markers.addLayer(
203
+ L.marker(position.latLng, {
204
+ icon: L.icon({
205
+ iconUrl: options.arrowUrl,
206
+ iconSize: options.arrowSize,
207
+ }),
208
+ // NB the following option is added by "leaflet-rotate"
209
+ rotation: angle * L.DomUtil.RAD_TO_DEG,
210
+ interactive: false,
211
+ })
212
+ );
213
+ }
209
214
  }
210
- }
211
215
 
212
- // create distance markers
213
- if (options.distance && i % 2 == 0) {
214
- if (preferCanvas) {
215
- markers.addLayer(
216
- new L.DistanceMarker(position.latLng, {
217
- label: text, // TODO: handle text rotation (leaflet-rotate)
218
- radius: 7,
219
- fillColor: '#fff',
220
- fillOpacity: 1,
221
- fillStyle: 'black',
222
- color: '#777',
223
- weight: 1,
224
- interactive: false,
225
- })
226
- );
227
- } else {
228
- markers.addLayer(
229
- L.marker(position.latLng, {
230
- title: text,
231
- icon: L.divIcon({
232
- className: options.cssClass,
233
- html: text,
234
- iconSize: options.iconSize
235
- }),
236
- interactive: false,
237
- })
238
- );
216
+ // create distance markers
217
+ if (options.distance && i % 2 == 0) {
218
+ if (preferCanvas) {
219
+ markers.addLayer(
220
+ new L.DistanceMarker(position.latLng, {
221
+ label: text, // TODO: handle text rotation (leaflet-rotate)
222
+ radius: 7,
223
+ fillColor: '#fff',
224
+ fillOpacity: 1,
225
+ fillStyle: 'black',
226
+ color: '#777',
227
+ weight: 1,
228
+ interactive: false,
229
+ })
230
+ );
231
+ } else {
232
+ markers.addLayer(
233
+ L.marker(position.latLng, {
234
+ title: text,
235
+ icon: L.divIcon({
236
+ className: options.cssClass,
237
+ html: text,
238
+ iconSize: options.iconSize
239
+ }),
240
+ interactive: false,
241
+ })
242
+ );
243
+ }
239
244
  }
240
245
  }
241
- }
246
+ });
242
247
 
243
248
  const updateMarkerVisibility = () => {
244
249
  let oldZoom = this._lastZoomLevel || 0;
@@ -1 +1 @@
1
- L.DistanceMarker=L.CircleMarker.extend({_updatePath:function(){let ctx=this._renderer._ctx,p=this._point;if(this.options.rotation=this.options.rotation||0,this.options.radius&&this._renderer._updateCircle&&this._renderer._updateCircle(this),this.options.icon&&this.options.icon.url)if(this.options.icon.element){const icon=this.options.icon;let cx=p.x+icon.offset.x,cy=p.y+icon.offset.y;ctx.save(),icon.rotate&&(ctx.translate(p.x,p.y),ctx.rotate(icon.rotate),cx=0,cy=0),ctx.drawImage(icon.element,cx-icon.size[0]/2,cy-icon.size[1]/2,icon.size[0],icon.size[1]),ctx.restore()}else{const icon=document.createElement("img");this.options.icon=L.extend({rotate:0,size:[40,40],offset:{x:0,y:0}},this.options.icon),this.options.icon.rotate+=this.options.rotation,this.options.icon.element=icon,icon.src=this.options.icon.url,icon.onload=()=>this.redraw(),icon.onerror=()=>this.options.icon=null}if(this.options.label){let cx=p.x,cy=p.y;ctx.save(),ctx.font=this.options.font||'normal 7pt "Helvetica Neue", Arial, Helvetica, sans-serif',ctx.textAlign="center",ctx.textBaseline="middle",ctx.fillStyle=this.options.fillStyle||"black",this.options.rotation&&(ctx.translate(p.x,p.y),ctx.rotate(this.options.rotation),cx=0,cy=0),this._map.getZoom()>17&&(ctx.fillStyle=this.options.strokeStyle||"black"),ctx.fillText(this.options.label,cx,cy),this.options.strokeStyle&&this._map.getZoom()<=17&&(ctx.strokeStyle=this.options.strokeStyle,ctx.strokeText(this.options.label,cx,cy)),ctx.restore()}}}),L.DistanceMarkers=L.LayerGroup.extend({options:{cssClass:"dist-marker",iconSize:[12,12],arrowSize:[10,10],arrowUrl:"data:image/svg+xml,%3Csvg transform='rotate(90)' xmlns='http://www.w3.org/2000/svg' width='560px' height='560px' viewBox='0 0 560 560'%3E%3Cpath stroke-width='35' fill='%23000' stroke='%23FFF' d='M280,40L522,525L280,420L38,525z'/%3E%3C/svg%3E",offset:1e3,showAll:12,textFunction:(distance,i,offset)=>i,distance:!0,direction:!0},initialize:function(line,map,options){this._layers={},this._zoomLayers={},options=L.setOptions(this,options);let preferCanvas=map.options.preferCanvas,showAll=Math.min(map.getMaxZoom(),options.showAll);preferCanvas||map.options.rotate||console.warn('Missing dependency: "leaflet-rotate"');let coords="function"==typeof line.getLatLngs?line.getLatLngs():line,accumulated=L.GeometryUtil.accumulatedLengths(line),length=accumulated.length>0?accumulated[accumulated.length-1]:0;for(let i=1,count=Math.floor(length/options.offset),j=0;i<=count;++i){let distance=options.offset*i;for(;j<accumulated.length-1&&accumulated[j]<distance;)++j;let p1=coords[j-1],p2=coords[j],m_line=L.polyline([p1,p2]),ratio=(distance-accumulated[j-1])/(accumulated[j]-accumulated[j-1]),position=L.GeometryUtil.interpolateOnLine(map,m_line,ratio),delta=map.project(p2).subtract(map.project(p1)),angle=Math.atan2(delta.y,delta.x),text=options.textFunction.call(this,distance,i,options.offset),zoom=this._minimumZoomLevelForItem(i,showAll),markers=this._zoomLayers[zoom]=this._zoomLayers[zoom]||L.layerGroup();options.direction&&(options.distance&&i%2==1||!options.distance)&&(preferCanvas?markers.addLayer(new L.DistanceMarker(p1,{radius:0,icon:{url:options.arrowUrl,size:options.arrowSize,rotate:0,offset:{x:0,y:0}},rotation:angle,interactive:!1})):markers.addLayer(L.marker(position.latLng,{icon:L.icon({iconUrl:options.arrowUrl,iconSize:options.arrowSize}),rotation:angle*L.DomUtil.RAD_TO_DEG,interactive:!1}))),options.distance&&i%2==0&&(preferCanvas?markers.addLayer(new L.DistanceMarker(position.latLng,{label:text,radius:7,fillColor:"#fff",fillOpacity:1,fillStyle:"black",color:"#777",weight:1,interactive:!1})):markers.addLayer(L.marker(position.latLng,{title:text,icon:L.divIcon({className:options.cssClass,html:text,iconSize:options.iconSize}),interactive:!1})))}const updateMarkerVisibility=()=>{let oldZoom=this._lastZoomLevel||0,newZoom=map.getZoom();if(newZoom>oldZoom)for(let i=oldZoom+1;i<=newZoom;++i)void 0!==this._zoomLayers[i]&&this.addLayer(this._zoomLayers[i]);else if(newZoom<oldZoom)for(let i=oldZoom;i>newZoom;--i)void 0!==this._zoomLayers[i]&&this.removeLayer(this._zoomLayers[i]);this._lastZoomLevel=newZoom};map.on("zoomend",updateMarkerVisibility),updateMarkerVisibility()},_minimumZoomLevelForItem:function(i,zoom){for(;i>0&&i%2==0;)--zoom,i=Math.floor(i/2);return zoom}}),L.Polyline.include({_originalOnAdd:L.Polyline.prototype.onAdd,_originalOnRemove:L.Polyline.prototype.onRemove,addDistanceMarkers:function(){this._map&&this._distanceMarkers&&this._map.addLayer(this._distanceMarkers)},removeDistanceMarkers:function(){this._map&&this._distanceMarkers&&this._map.removeLayer(this._distanceMarkers)},onAdd:function(map){this._originalOnAdd(map);let opts=this.options.distanceMarkers||{};this.options.distanceMarkers&&(this._distanceMarkers=this._distanceMarkers||new L.DistanceMarkers(this,map,opts)),void 0!==opts.lazy&&!1!==opts.lazy||this.addDistanceMarkers()},onRemove:function(map){this.removeDistanceMarkers(),this._originalOnRemove(map)}});
1
+ L.DistanceMarker=L.CircleMarker.extend({_updatePath:function(){let ctx=this._renderer._ctx,p=this._point;if(this.options.rotation=this.options.rotation||0,this.options.radius&&this._renderer._updateCircle&&this._renderer._updateCircle(this),this.options.icon&&this.options.icon.url)if(this.options.icon.element){const icon=this.options.icon;let cx=p.x+icon.offset.x,cy=p.y+icon.offset.y;ctx.save(),icon.rotate&&(ctx.translate(p.x,p.y),ctx.rotate(icon.rotate),cx=0,cy=0),ctx.drawImage(icon.element,cx-icon.size[0]/2,cy-icon.size[1]/2,icon.size[0],icon.size[1]),ctx.restore()}else{const icon=document.createElement("img");this.options.icon=L.extend({rotate:0,size:[40,40],offset:{x:0,y:0}},this.options.icon),this.options.icon.rotate+=this.options.rotation,this.options.icon.element=icon,icon.src=this.options.icon.url,icon.onload=()=>this.redraw(),icon.onerror=()=>this.options.icon=null}if(this.options.label){let cx=p.x,cy=p.y;ctx.save(),ctx.font=this.options.font||'normal 7pt "Helvetica Neue", Arial, Helvetica, sans-serif',ctx.textAlign="center",ctx.textBaseline="middle",ctx.fillStyle=this.options.fillStyle||"black",this.options.rotation&&(ctx.translate(p.x,p.y),ctx.rotate(this.options.rotation),cx=0,cy=0),this._map.getZoom()>17&&(ctx.fillStyle=this.options.strokeStyle||"black"),ctx.fillText(this.options.label,cx,cy),this.options.strokeStyle&&this._map.getZoom()<=17&&(ctx.strokeStyle=this.options.strokeStyle,ctx.strokeText(this.options.label,cx,cy)),ctx.restore()}}}),L.DistanceMarkers=L.LayerGroup.extend({options:{cssClass:"dist-marker",iconSize:[12,12],arrowSize:[10,10],arrowUrl:"data:image/svg+xml,%3Csvg transform='rotate(90)' xmlns='http://www.w3.org/2000/svg' width='560px' height='560px' viewBox='0 0 560 560'%3E%3Cpath stroke-width='35' fill='%23000' stroke='%23FFF' d='M280,40L522,525L280,420L38,525z'/%3E%3C/svg%3E",offset:1e3,showAll:12,textFunction:(distance,i,offset)=>i,distance:!0,direction:!0},initialize:function(line,map,options){this._layers={},this._zoomLayers={},options=L.setOptions(this,options);let preferCanvas=map.options.preferCanvas,showAll=Math.min(map.getMaxZoom(),options.showAll);preferCanvas||map.options.rotate||console.warn('Missing dependency: "leaflet-rotate"');let coords="function"==typeof line.getLatLngs?line.getLatLngs():line;coords=L.LineUtil.isFlat(coords)?[coords]:coords,coords.forEach(latlngs=>{let accumulated=L.GeometryUtil.accumulatedLengths(latlngs),length=accumulated.length>0?accumulated[accumulated.length-1]:0;for(let i=1,count=Math.floor(length/options.offset),j=0;i<=count;++i){let distance=options.offset*i;for(;j<accumulated.length-1&&accumulated[j]<distance;)++j;let p1=latlngs[j-1],p2=latlngs[j],m_line=L.polyline([p1,p2]),ratio=(distance-accumulated[j-1])/(accumulated[j]-accumulated[j-1]),position=L.GeometryUtil.interpolateOnLine(map,m_line,ratio),delta=map.project(p2).subtract(map.project(p1)),angle=Math.atan2(delta.y,delta.x),text=options.textFunction.call(this,distance,i,options.offset),zoom=this._minimumZoomLevelForItem(i,showAll),markers=this._zoomLayers[zoom]=this._zoomLayers[zoom]||L.layerGroup();options.direction&&(options.distance&&i%2==1||!options.distance)&&(preferCanvas?markers.addLayer(new L.DistanceMarker(p1,{radius:0,icon:{url:options.arrowUrl,size:options.arrowSize,rotate:0,offset:{x:0,y:0}},rotation:angle,interactive:!1})):markers.addLayer(L.marker(position.latLng,{icon:L.icon({iconUrl:options.arrowUrl,iconSize:options.arrowSize}),rotation:angle*L.DomUtil.RAD_TO_DEG,interactive:!1}))),options.distance&&i%2==0&&(preferCanvas?markers.addLayer(new L.DistanceMarker(position.latLng,{label:text,radius:7,fillColor:"#fff",fillOpacity:1,fillStyle:"black",color:"#777",weight:1,interactive:!1})):markers.addLayer(L.marker(position.latLng,{title:text,icon:L.divIcon({className:options.cssClass,html:text,iconSize:options.iconSize}),interactive:!1})))}});const updateMarkerVisibility=()=>{let oldZoom=this._lastZoomLevel||0,newZoom=map.getZoom();if(newZoom>oldZoom)for(let i=oldZoom+1;i<=newZoom;++i)void 0!==this._zoomLayers[i]&&this.addLayer(this._zoomLayers[i]);else if(newZoom<oldZoom)for(let i=oldZoom;i>newZoom;--i)void 0!==this._zoomLayers[i]&&this.removeLayer(this._zoomLayers[i]);this._lastZoomLevel=newZoom};map.on("zoomend",updateMarkerVisibility),updateMarkerVisibility()},_minimumZoomLevelForItem:function(i,zoom){for(;i>0&&i%2==0;)--zoom,i=Math.floor(i/2);return zoom}}),L.Polyline.include({_originalOnAdd:L.Polyline.prototype.onAdd,_originalOnRemove:L.Polyline.prototype.onRemove,addDistanceMarkers:function(){this._map&&this._distanceMarkers&&this._map.addLayer(this._distanceMarkers)},removeDistanceMarkers:function(){this._map&&this._distanceMarkers&&this._map.removeLayer(this._distanceMarkers)},onAdd:function(map){this._originalOnAdd(map);let opts=this.options.distanceMarkers||{};this.options.distanceMarkers&&(this._distanceMarkers=this._distanceMarkers||new L.DistanceMarkers(this,map,opts)),void 0!==opts.lazy&&!1!==opts.lazy||this.addDistanceMarkers()},onRemove:function(map){this.removeDistanceMarkers(),this._originalOnRemove(map)}});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raruto/leaflet-elevation",
3
- "version": "2.0.0",
3
+ "version": "2.0.3",
4
4
  "description": "A Leaflet plugin that allows to add elevation profiles using d3js",
5
5
  "main": "dist/leaflet-elevation.min.js",
6
6
  "module": "src/index.js",
@@ -1,4 +1,4 @@
1
- import * as D3 from './components.js';
1
+ import * as D3 from './d3.js';
2
2
 
3
3
  const _ = L.Control.Elevation.Utils;
4
4
 
@@ -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();
@@ -1,4 +1,4 @@
1
- import * as D3 from './components.js';
1
+ import * as D3 from './d3.js';
2
2
 
3
3
  const _ = L.Control.Elevation.Utils;
4
4
 
File without changes