@abi-software/flatmap-viewer 2.3.2-b.4 → 2.3.3-b.2

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.rst CHANGED
@@ -38,7 +38,7 @@ The map server endpoint is specified as ``MAP_ENDPOINT`` in ``src/main.js``. It
38
38
  Package Installation
39
39
  ====================
40
40
 
41
- * ``npm install @abi-software/flatmap-viewer@2.3.2-b.4``
41
+ * ``npm install @abi-software/flatmap-viewer@2.3.3-b.2``
42
42
 
43
43
  Documentation
44
44
  -------------
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abi-software/flatmap-viewer",
3
- "version": "2.3.2-b.4",
3
+ "version": "2.3.3-b.2",
4
4
  "description": "Flatmap viewer using Maplibre GL",
5
5
  "repository": "https://github.com/AnatomicMaps/flatmap-viewer.git",
6
6
  "main": "src/main.js",
package/src/annotation.js CHANGED
@@ -475,6 +475,8 @@ export class Annotator
475
475
  let label = '';
476
476
  if (feature.properties.models) {
477
477
  label = ` -- ${feature.properties.label.split('\n')[0]} (${feature.properties.models})`;
478
+ } else if (feature.properties.label) {
479
+ label = ` -- ${feature.properties.label.split('\n')[0]}`;
478
480
  }
479
481
  featureList.push(`<option value="${feature.id}" ${selected}>${annotated ? '*' : '&nbsp;'} ${feature.properties.id} -- ${feature.properties.kind}${label}</option>`);
480
482
  featureProperties.set(+feature.id, feature.properties);
@@ -526,6 +526,73 @@ export class NerveControl
526
526
 
527
527
  //==============================================================================
528
528
 
529
+ export class AnnotatedControl
530
+ {
531
+ constructor(ui, options={excludeAnnotated: false})
532
+ {
533
+ this.__ui = ui;
534
+ this.__map = undefined;
535
+ this.__exclude = options.excludeAnnotated || false;
536
+ }
537
+
538
+ getDefaultPosition()
539
+ //==================
540
+ {
541
+ return 'top-right';
542
+ }
543
+
544
+ onAdd(map)
545
+ //========
546
+ {
547
+ this.__map = map;
548
+ this.__container = document.createElement('div');
549
+ this.__container.className = 'maplibregl-ctrl';
550
+
551
+ this.__button = document.createElement('button');
552
+ this.__button.id = 'map-annotated-button';
553
+ this.__button.className = 'control-button text-button';
554
+ this.__button.setAttribute('type', 'button');
555
+ this.__button.setAttribute('aria-label', 'Show/hide annotated paths');
556
+ this.__button.textContent = 'UNANN';
557
+ this.__button.title = 'Show/hide annotated paths';
558
+ this.__container.appendChild(this.__button);
559
+
560
+ this.__container.addEventListener('click', this.onClick_.bind(this));
561
+ this.__setBackground();
562
+ return this.__container;
563
+ }
564
+
565
+ __setBackground()
566
+ //===============
567
+ {
568
+ if (this.__exclude) {
569
+ this.__button.setAttribute('style', 'background: red');
570
+ } else {
571
+ this.__button.removeAttribute('style');
572
+ }
573
+ }
574
+
575
+ onRemove()
576
+ //========
577
+ {
578
+ this.__container.parentNode.removeChild(this.__container);
579
+ this.__map = undefined;
580
+ }
581
+
582
+ onClick_(event)
583
+ //=============
584
+ {
585
+ if (event.target.id === 'map-annotated-button') {
586
+ this.__exclude = !this.__exclude;
587
+ this.__setBackground();
588
+ this.__ui.excludeAnnotated(this.__exclude);
589
+ }
590
+ event.stopPropagation();
591
+ }
592
+ }
593
+
594
+ //==============================================================================
595
+
529
596
  export class BackgroundControl
530
597
  {
531
598
  constructor(flatmap)
@@ -194,8 +194,8 @@ export class InfoControl
194
194
  const featureIds = [];
195
195
  const displayFeatures = [];
196
196
  for (const feat of featureList) {
197
- if (featureIds.indexOf(feat['id']) < 0) {
198
- featureIds.push(feat['id']);
197
+ if (featureIds.indexOf(feat.id) < 0) {
198
+ featureIds.push(feat.id);
199
199
  const displayFeat = {};
200
200
  displayProperties.forEach(prop => {
201
201
  if (prop === 'properties') {
@@ -77,6 +77,7 @@ class FlatMap
77
77
  this.__datasetToFeatureIds = new Map();
78
78
  this.__modelToFeatureIds = new Map();
79
79
  this.__mapSourceToFeatureIds = new Map();
80
+
80
81
  for (const [featureId, annotation] of Object.entries(mapDescription.annotations)) {
81
82
  this.__addAnnotation(featureId, annotation);
82
83
  this.__searchIndex.indexMetadata(featureId, annotation);
@@ -176,7 +177,7 @@ class FlatMap
176
177
  this._initialState = null;
177
178
  this._minimap = null;
178
179
 
179
- this._map.on('idle', () => {
180
+ this._map.on('load', () => {
180
181
  if (this._userInteractions === null) {
181
182
  this.setupUserInteractions_();
182
183
  } else if (this._initialState === null) {
@@ -40,7 +40,7 @@ import {VECTOR_TILES_SOURCE} from './styling';
40
40
  import {SystemsManager} from './systems';
41
41
 
42
42
  import {displayedProperties, InfoControl} from './controls/info';
43
- import {BackgroundControl, LayerControl, NerveControl,
43
+ import {AnnotatedControl, BackgroundControl, LayerControl, NerveControl,
44
44
  SCKANControl} from './controls/controls';
45
45
  import {PathControl} from './controls/paths';
46
46
  import {SearchControl} from './controls/search';
@@ -189,6 +189,7 @@ export class UserInteractions
189
189
  if (flatmap.options.style === 'functional') {
190
190
  this._map.addControl(new SystemsControl(flatmap, this.__systemsManager.systems));
191
191
  this._map.addControl(new SCKANControl(flatmap, flatmap.options.layerOptions));
192
+ this._map.addControl(new AnnotatedControl(this, flatmap.options.layerOptions));
192
193
  }
193
194
  }
194
195
 
@@ -654,10 +655,11 @@ export class UserInteractions
654
655
  this._currentPopup.remove();
655
656
  }
656
657
 
657
- // Highlight the feature
658
-
659
- this.unselectFeatures();
660
- this.selectFeature(featureId);
658
+ if (!(options && options.preserveSelection)) {
659
+ // Highlight the feature
660
+ this.unselectFeatures();
661
+ this.selectFeature(featureId);
662
+ }
661
663
 
662
664
  // Find the pop-up's postion
663
665
 
@@ -830,7 +832,7 @@ export class UserInteractions
830
832
  let info = '';
831
833
  let tooltip = '';
832
834
  if (displayInfo) {
833
- if (!'tooltip' in features[0].properties) {
835
+ if (!('tooltip' in features[0].properties)) {
834
836
  this.__activateFeature(features[0]);
835
837
  }
836
838
  info = this._infoControl.featureInformation(features, event.lngLat);
@@ -854,8 +856,7 @@ export class UserInteractions
854
856
  }
855
857
  } else {
856
858
  let labelledFeatures = features.filter(feature => (('hyperlink' in feature.properties
857
- || 'label' in feature.properties
858
- || 'node' in feature.properties)
859
+ || 'label' in feature.properties)
859
860
  && (!('tooltip' in feature.properties)
860
861
  || feature.properties.tooltip)))
861
862
  .sort((a, b) => (a.properties.area - b.properties.area));
@@ -895,7 +896,9 @@ export class UserInteractions
895
896
  //htmlList.push(`<span class="info-name">Scale:</span>`);
896
897
  //htmlList.push(`<span class="info-value">${feature.properties.scale}</span>`);
897
898
  }
898
- info = `<div id="info-control-info">${htmlList.join('\n')}</div>`;
899
+ if (!this._flatmap.options.debug) {
900
+ info = `<div id="info-control-info">${htmlList.join('\n')}</div>`;
901
+ }
899
902
  }
900
903
  this.__activateFeature(feature);
901
904
  this.__activateRelatedFeatures(feature);
@@ -905,7 +908,7 @@ export class UserInteractions
905
908
  }
906
909
  }
907
910
 
908
- if (displayInfo || this._flatmap.options.debug) {
911
+ if (info !== '') {
909
912
  this._infoControl.show(info);
910
913
  }
911
914
  this.__showToolTip(tooltip, event.lngLat, tooltipFeature);
@@ -1096,6 +1099,12 @@ export class UserInteractions
1096
1099
  this._layerManager.enableSckanPaths(sckanState, enable);
1097
1100
  }
1098
1101
 
1102
+ excludeAnnotated(exclude=false)
1103
+ //=============================
1104
+ {
1105
+ this._layerManager.setPaint({excludeAnnotated: exclude});
1106
+ }
1107
+
1099
1108
  //==============================================================================
1100
1109
 
1101
1110
  // Marker handling
@@ -1179,6 +1188,9 @@ export class UserInteractions
1179
1188
  this.__markerIdByMarker.set(marker, markerId);
1180
1189
  this.__markerIdByFeatureId.set(+featureId, markerId);
1181
1190
  this.__annotationByMarkerId.set(markerId, annotation);
1191
+ if (!this.__featureEnabled(this.mapFeature(+featureId))) {
1192
+ markerElement.style.visibility = 'hidden';
1193
+ }
1182
1194
  }
1183
1195
  }
1184
1196
  if (markerId === -1) {
package/src/layers.js CHANGED
@@ -123,7 +123,6 @@ class MapFeatureLayers extends MapStylingLayers
123
123
  this.__addStyleLayer(style.FeatureLineLayer);
124
124
  this.__addStyleLayer(style.FeatureBorderLayer);
125
125
  this.__addStyleLayer(style.CentrelineNodeFillLayer);
126
- this.__addStyleLayer(style.CentrelineNodeBorderLayer);
127
126
  }
128
127
  this.__addPathwayStyleLayers();
129
128
  if (vectorFeatures) {
package/src/styling.js CHANGED
@@ -35,7 +35,7 @@ const COLOUR_ANNOTATED = '#0F0';
35
35
  const COLOUR_SELECTED = '#0F0';
36
36
  const COLOUR_HIDDEN = '#D8D8D8';
37
37
 
38
- const CENTRELINE_ACTIVE = '#444';
38
+ const CENTRELINE_ACTIVE = '#888';
39
39
  const CENTRELINE_COLOUR = '#CCC';
40
40
 
41
41
  const FEATURE_SELECTED_BORDER = 'black';
@@ -161,7 +161,7 @@ export class FeatureFillLayer extends VectorStyleLayer
161
161
  'fill-opacity': [
162
162
  'case',
163
163
  ['boolean', ['feature-state', 'hidden'], false], 0.1,
164
- ['boolean', ['feature-state', 'selected'], false], 0.7,
164
+ ['boolean', ['feature-state', 'selected'], false], 0.5,
165
165
  ['has', 'opacity'], ['get', 'opacity'],
166
166
  ['has', 'colour'], 1.0,
167
167
  ['boolean', ['feature-state', 'active'], false], 0.7,
@@ -418,23 +418,24 @@ export class AnnotatedPathLayer extends VectorStyleLayer
418
418
 
419
419
  paintStyle(options={}, changes=false)
420
420
  {
421
- const dimmed = 'dimmed' in options && options.dimmed;
421
+ const exclude = 'excludeAnnotated' in options && options.excludeAnnotated;
422
422
  const paintStyle = {
423
423
  'line-color': COLOUR_ANNOTATED,
424
424
  'line-dasharray': [5, 0.5, 3, 0.5],
425
425
  'line-opacity': [
426
426
  'case',
427
427
  ['boolean', ['feature-state', 'hidden'], false], 0.05,
428
- ['boolean', ['feature-state', 'annotated'], false],
429
- (dimmed ? 0.1 : 0.8),
428
+ ['boolean', ['feature-state', 'annotated'], false],
429
+ (exclude ? 0.05 : 0.8),
430
430
  0.6
431
431
  ],
432
432
  'line-width': [
433
433
  'let',
434
434
  'width',
435
435
  ['case',
436
+ ['boolean', ['feature-state', 'hidden'], false], 0.0,
436
437
  ['boolean', ['feature-state', 'annotated'], false],
437
- ['*', 1.2, ['case', ['has', 'stroke-width'], ['get', 'stroke-width'], 1.0]],
438
+ exclude ? 0.0 : (['*', 1.2, ['case', ['has', 'stroke-width'], ['get', 'stroke-width'], 1.0]]),
438
439
  0.0
439
440
  ],
440
441
  STROKE_INTERPOLATION
@@ -498,15 +499,20 @@ export class PathLineLayer extends VectorStyleLayer
498
499
  paintStyle(options={}, changes=false)
499
500
  {
500
501
  const dimmed = 'dimmed' in options && options.dimmed;
502
+ const exclude = 'excludeAnnotated' in options && options.excludeAnnotated;
501
503
  const paintStyle = {
502
504
  'line-color': [
503
- 'case',
504
- ['boolean', ['feature-state', 'selected'], false], COLOUR_SELECTED,
505
- ['boolean', ['feature-state', 'hidden'], false], COLOUR_HIDDEN,
506
- ['==', ['get', 'type'], 'bezier'], 'red',
507
- ['==', ['get', 'kind'], 'unknown'], '#888',
508
- ...PATH_STYLE_RULES,
509
- '#888'
505
+ 'let', 'active', ['to-number', ['feature-state', 'active'], 0],
506
+ [ 'case',
507
+ ['all',
508
+ ['==', ['var', 'active'], 0],
509
+ ['boolean', ['feature-state', 'selected'], false],
510
+ ], COLOUR_SELECTED,
511
+ ['boolean', ['feature-state', 'hidden'], false], COLOUR_HIDDEN,
512
+ ['==', ['get', 'type'], 'bezier'], 'red',
513
+ ...PATH_STYLE_RULES,
514
+ '#888'
515
+ ]
510
516
  ],
511
517
  'line-opacity': this.__highlight ? [
512
518
  'case',
@@ -544,6 +550,7 @@ export class PathLineLayer extends VectorStyleLayer
544
550
  ['boolean', ['feature-state', 'active'], false], 0.0,
545
551
  0.6
546
552
  ],
553
+ ['case', ['boolean', ['feature-state', 'annotated'], false], (exclude ? 0.0 : 1.0), 1.0],
547
554
  ['case', ['has', 'stroke-width'], ['get', 'stroke-width'], 1.0]
548
555
  ],
549
556
  STROKE_INTERPOLATION
@@ -622,7 +629,7 @@ class CentrelineLayer extends VectorStyleLayer
622
629
  ['boolean', ['feature-state', 'hidden'], false], 0.01,
623
630
  ['boolean', ['feature-state', 'selected'], false], 1.0,
624
631
  ['boolean', ['feature-state', 'active'], false], 1.0,
625
- 0.8
632
+ (this.__type == 'edge') ? 0.4 : 0.8
626
633
  ],
627
634
  'line-width': [
628
635
  'let',
@@ -648,7 +655,7 @@ class CentrelineLayer extends VectorStyleLayer
648
655
  ],
649
656
  'paint': this.paintStyle(options),
650
657
  'layout': {
651
- 'line-cap': 'square',
658
+ 'line-cap': 'round',
652
659
  'line-join': 'bevel'
653
660
  }
654
661
  };
@@ -688,8 +695,13 @@ export class CentrelineNodeFillLayer extends VectorStyleLayer
688
695
  {
689
696
  const showNodes = options.showCentrelines || false;
690
697
  const paintStyle = {
691
- 'fill-color': '#AFA202',
692
- 'fill-opacity': showNodes ? 0.7 : 0.01
698
+ 'fill-color': [
699
+ 'case',
700
+ ['boolean', ['feature-state', 'selected'], false], COLOUR_SELECTED,
701
+ ['boolean', ['feature-state', 'active'], false], CENTRELINE_ACTIVE,
702
+ CENTRELINE_COLOUR
703
+ ],
704
+ 'fill-opacity': showNodes ? 0.8 : 0.01
693
705
  }
694
706
  return super.changedPaintStyle(paintStyle, changes);
695
707
  }
@@ -723,9 +735,14 @@ export class CentrelineNodeBorderLayer extends VectorStyleLayer
723
735
  {
724
736
  const showNodes = options.showCentrelines || false;
725
737
  const paintStyle = {
726
- 'line-color': '#AFA202',
727
- 'line-opacity': showNodes ? 0.7 : 0.01,
728
- 'line-width': 0.5
738
+ 'line-color': '#000',
739
+ 'line-opacity': showNodes ? 0.1 : 0.01,
740
+ 'line-width': [
741
+ 'let',
742
+ 'width',
743
+ 0.2,
744
+ STROKE_INTERPOLATION
745
+ ]
729
746
  }
730
747
  return super.changedPaintStyle(paintStyle, changes);
731
748
  }
@@ -769,8 +786,8 @@ export class FeatureNerveLayer extends VectorStyleLayer
769
786
  'line-color': [
770
787
  'case',
771
788
  ['boolean', ['feature-state', 'hidden'], false], COLOUR_HIDDEN,
772
- ['boolean', ['feature-state', 'active'], false], NERVE_ACTIVE,
773
789
  ['boolean', ['feature-state', 'selected'], false], NERVE_SELECTED,
790
+ ['boolean', ['feature-state', 'active'], false], NERVE_ACTIVE,
774
791
  '#888'
775
792
  ],
776
793
  'line-opacity': [
@@ -852,7 +869,41 @@ export class NervePolygonFill extends VectorStyleLayer
852
869
  super(id, 'nerve-fill', sourceLayer);
853
870
  }
854
871
 
855
- style(options)
872
+ paintStyle(options={}, changes=false)
873
+ {
874
+ const dimmed = 'dimmed' in options && options.dimmed;
875
+ const paintStyle = {
876
+ 'fill-color': [
877
+ 'let', 'active', ['to-number', ['feature-state', 'active'], 0],
878
+ [ 'case',
879
+ ['all',
880
+ ['==', ['var', 'active'], 0],
881
+ ['==', ['get', 'type'], 'arrow'],
882
+ ['boolean', ['feature-state', 'selected'], false]
883
+ ], COLOUR_SELECTED,
884
+ ['==', ['get', 'kind'], 'bezier-end'], 'red',
885
+ ['==', ['get', 'kind'], 'bezier-control'], 'green',
886
+ ...PATH_STYLE_RULES,
887
+ 'white'
888
+ ]
889
+ ],
890
+ 'fill-opacity': [
891
+ 'case',
892
+ ['boolean', ['feature-state', 'hidden'], false], 0.01,
893
+ ['boolean', ['feature-state', 'selected'], false], 0.8,
894
+ ['boolean', ['feature-state', 'active'], false], 0.9,
895
+ ['==', ['get', 'type'], 'bezier'], 0.9,
896
+ ['any',
897
+ ['==', ['get', 'type'], 'arrow'],
898
+ ['==', ['get', 'type'], 'junction']
899
+ ], dimmed ? 0.1 : 0.5,
900
+ 0.01
901
+ ]
902
+ };
903
+ return super.changedPaintStyle(paintStyle, changes);
904
+ }
905
+
906
+ style(options={})
856
907
  {
857
908
  return {
858
909
  ...super.style(),
@@ -861,27 +912,14 @@ export class NervePolygonFill extends VectorStyleLayer
861
912
  'all',
862
913
  ['==', '$type', 'Polygon'],
863
914
  ['any',
915
+ ['==', 'type', 'arrow'],
864
916
  ['==', 'type', 'bezier'],
865
917
  ['==', 'type', 'junction'],
866
918
  ['==', 'type', 'nerve'],
867
919
  ['==', 'type', 'nerve-section']
868
920
  ]
869
921
  ],
870
- 'paint': {
871
- 'fill-color': [
872
- 'case',
873
- ['==', ['get', 'kind'], 'bezier-end'], 'red',
874
- ['==', ['get', 'kind'], 'bezier-control'], 'green',
875
- ...PATH_STYLE_RULES,
876
- 'white'
877
- ],
878
- 'fill-opacity': [
879
- 'case',
880
- ['==', ['get', 'type'], 'bezier'], 0.9,
881
- ['==', ['get', 'type'], 'junction'], 0.4,
882
- 0.01
883
- ]
884
- }
922
+ 'paint': this.paintStyle(options)
885
923
  };
886
924
  }
887
925
  }