@abi-software/flatmap-viewer 2.2.2-beta.4 → 2.2.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.
- package/README.rst +1 -1
- package/package.json +1 -1
- package/src/controls.js +2 -2
- package/src/flatmap-viewer.js +3 -3
- package/src/interactions.js +107 -73
- package/src/styling.js +10 -8
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.2.
|
|
41
|
+
* ``npm install @abi-software/flatmap-viewer@2.2.3``
|
|
42
42
|
|
|
43
43
|
Documentation
|
|
44
44
|
-------------
|
package/package.json
CHANGED
package/src/controls.js
CHANGED
|
@@ -113,11 +113,11 @@ export class PathControl
|
|
|
113
113
|
this._button = document.createElement('button');
|
|
114
114
|
this._button.id = 'nerve-key-button';
|
|
115
115
|
this._button.className = 'control-button';
|
|
116
|
-
this._button.title = 'Nerve paths legend';
|
|
117
116
|
this._button.setAttribute('type', 'button');
|
|
118
117
|
this._button.setAttribute('aria-label', 'Nerve paths legend');
|
|
119
118
|
this._button.setAttribute('legend-visible', 'false');
|
|
120
|
-
this._button.textContent = '
|
|
119
|
+
this._button.textContent = 'PATHS';
|
|
120
|
+
this._button.title = 'Show/hide neuron paths';
|
|
121
121
|
this._container.appendChild(this._button);
|
|
122
122
|
|
|
123
123
|
this._container.addEventListener('click', this.onClick_.bind(this));
|
package/src/flatmap-viewer.js
CHANGED
|
@@ -949,11 +949,11 @@ class FlatMap
|
|
|
949
949
|
}
|
|
950
950
|
}
|
|
951
951
|
|
|
952
|
-
showSearchResults(searchResults
|
|
953
|
-
|
|
952
|
+
showSearchResults(searchResults)
|
|
953
|
+
//==============================
|
|
954
954
|
{
|
|
955
955
|
if (this._userInteractions !== null) {
|
|
956
|
-
this._userInteractions.
|
|
956
|
+
this._userInteractions.showSearchResults(searchResults.featureIds);
|
|
957
957
|
}
|
|
958
958
|
}
|
|
959
959
|
|
package/src/interactions.js
CHANGED
|
@@ -423,40 +423,6 @@ export class UserInteractions
|
|
|
423
423
|
this._modal = false;
|
|
424
424
|
}
|
|
425
425
|
|
|
426
|
-
enablePaths_(enable, event)
|
|
427
|
-
//=========================
|
|
428
|
-
{
|
|
429
|
-
this._contextMenu.hide();
|
|
430
|
-
const nodeId = event.target.getAttribute('featureId');
|
|
431
|
-
this.enablePathFeatures_(enable, this._pathways.pathFeatureIds(nodeId));
|
|
432
|
-
this.__clearModal();
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
enablePathFeatures_(enable, featureIds)
|
|
436
|
-
//=====================================
|
|
437
|
-
{
|
|
438
|
-
for (const featureId of featureIds) {
|
|
439
|
-
const feature = this.mapFeature_(featureId);
|
|
440
|
-
if (enable) {
|
|
441
|
-
this._map.removeFeatureState(feature, 'hidden');
|
|
442
|
-
} else {
|
|
443
|
-
this._map.setFeatureState(feature, { 'hidden': true });
|
|
444
|
-
this._disabledPathFeatures = true;
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
togglePaths()
|
|
450
|
-
//===========
|
|
451
|
-
{
|
|
452
|
-
if (this._disabledPathFeatures){
|
|
453
|
-
this.enablePathFeatures_(true, this._pathways.allFeatureIds());
|
|
454
|
-
this._disabledPathFeatures = false;
|
|
455
|
-
} else {
|
|
456
|
-
this.enablePathFeatures_(false, this._pathways.allFeatureIds());
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
|
|
460
426
|
reset()
|
|
461
427
|
//=====
|
|
462
428
|
{
|
|
@@ -521,6 +487,12 @@ export class UserInteractions
|
|
|
521
487
|
}
|
|
522
488
|
}
|
|
523
489
|
|
|
490
|
+
showSearchResults(featureIds)
|
|
491
|
+
//===========================
|
|
492
|
+
{
|
|
493
|
+
this.zoomToFeatures(featureIds, {highlight: true, noZoomIn: true});
|
|
494
|
+
}
|
|
495
|
+
|
|
524
496
|
/**
|
|
525
497
|
* Zoom map to features.
|
|
526
498
|
*
|
|
@@ -528,19 +500,23 @@ export class UserInteractions
|
|
|
528
500
|
* @param {Object} [options]
|
|
529
501
|
* @param {boolean} [options.select=true] Select the features zoomed to
|
|
530
502
|
* @param {boolean} [options.highlight=false] Highlight the features zoomed to
|
|
531
|
-
* @param {
|
|
503
|
+
* @param {boolean} [options.noZoomIn=false] Don't zoom in (although zoom out as necessary)
|
|
504
|
+
* @param {number} [options.padding=10] Padding in pixels around the composite bounding box
|
|
532
505
|
*/
|
|
533
506
|
zoomToFeatures(featureIds, options=null)
|
|
534
507
|
//======================================
|
|
535
508
|
{
|
|
536
|
-
options = utils.setDefaultOptions(options, {select: true, highlight: false, padding:
|
|
509
|
+
options = utils.setDefaultOptions(options, {select: true, highlight: false, noZoomIn: false, padding:10});
|
|
537
510
|
const select = (options.select === true);
|
|
538
511
|
const highlight = (options.highlight === true);
|
|
539
|
-
const padding = options.padding || 100;
|
|
540
512
|
if (featureIds.length) {
|
|
541
513
|
this.unhighlightFeatures_();
|
|
542
514
|
if (select) this.__unselectFeatures();
|
|
543
515
|
let bbox = null;
|
|
516
|
+
if (options.noZoomIn) {
|
|
517
|
+
const bounds = this._map.getBounds().toArray();
|
|
518
|
+
bbox = [...bounds[0], ...bounds[1]];
|
|
519
|
+
}
|
|
544
520
|
for (const featureId of featureIds) {
|
|
545
521
|
const annotation = this._flatmap.annotation(featureId);
|
|
546
522
|
if (annotation) {
|
|
@@ -565,7 +541,7 @@ export class UserInteractions
|
|
|
565
541
|
}
|
|
566
542
|
if (bbox !== null) {
|
|
567
543
|
this._map.fitBounds(bbox, {
|
|
568
|
-
padding: padding,
|
|
544
|
+
padding: options.padding,
|
|
569
545
|
animate: false
|
|
570
546
|
});
|
|
571
547
|
}
|
|
@@ -640,14 +616,17 @@ export class UserInteractions
|
|
|
640
616
|
const tooltips = [];
|
|
641
617
|
for (const lineFeature of lineFeatures) {
|
|
642
618
|
const properties = lineFeature.properties;
|
|
643
|
-
if (
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
619
|
+
if (this.__enabledFeature(lineFeature)) {
|
|
620
|
+
const properties = lineFeature.properties;
|
|
621
|
+
if ('label' in properties
|
|
622
|
+
&& (!('tooltip' in properties) || properties.tooltip)
|
|
623
|
+
&& !('labelled' in properties)) {
|
|
624
|
+
let tooltip = '';
|
|
625
|
+
const label = properties.label;
|
|
626
|
+
const cleanLabel = (label.substr(0, 1).toUpperCase() + label.substr(1)).replaceAll("\n", "<br/>");
|
|
627
|
+
if (!tooltips.includes(cleanLabel)) {
|
|
628
|
+
tooltips.push(cleanLabel);
|
|
629
|
+
}
|
|
651
630
|
}
|
|
652
631
|
}
|
|
653
632
|
}
|
|
@@ -682,10 +661,13 @@ export class UserInteractions
|
|
|
682
661
|
__featureEvent(type, feature)
|
|
683
662
|
//===========================
|
|
684
663
|
{
|
|
685
|
-
if (feature
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
664
|
+
if (this.__enabledFeature(feature)) {
|
|
665
|
+
if (feature.sourceLayer === PATHWAYS_LAYER) { // I suspect this is never true as source layer
|
|
666
|
+
// names are like `neural_routes_pathways`
|
|
667
|
+
return this._flatmap.featureEvent(type, this._pathways.pathProperties(feature));
|
|
668
|
+
} else if ('properties' in feature) {
|
|
669
|
+
return this._flatmap.featureEvent(type, feature.properties);
|
|
670
|
+
}
|
|
689
671
|
}
|
|
690
672
|
return false;
|
|
691
673
|
}
|
|
@@ -754,18 +736,22 @@ export class UserInteractions
|
|
|
754
736
|
}
|
|
755
737
|
info = this._infoControl.featureInformation(features, event.lngLat);
|
|
756
738
|
}
|
|
757
|
-
const lineFeatures = features.filter(feature => (
|
|
758
|
-
|
|
759
|
-
|
|
739
|
+
const lineFeatures = features.filter(feature => ('centreline' in feature.properties
|
|
740
|
+
|| ('type' in feature.properties
|
|
741
|
+
&& feature.properties.type.startsWith('line')) ));
|
|
760
742
|
if (lineFeatures.length > 0) {
|
|
761
743
|
tooltip = this.lineTooltip_(lineFeatures);
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
this.
|
|
765
|
-
const
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
744
|
+
const enabledFeatures = lineFeatures.filter(feature => this.__enabledFeature(feature));
|
|
745
|
+
if (enabledFeatures.length > 0) {
|
|
746
|
+
tooltip = this.lineTooltip_(enabledFeatures);
|
|
747
|
+
for (const lineFeature of enabledFeatures) {
|
|
748
|
+
const lineFeatureId = +lineFeature.properties.featureId; // Ensure numeric
|
|
749
|
+
this.activateFeature_(lineFeature);
|
|
750
|
+
const lineIds = new Set(enabledFeatures.map(f => f.properties.featureId));
|
|
751
|
+
for (const featureId of this._pathways.lineFeatureIds(lineIds)) {
|
|
752
|
+
if (+featureId !== lineFeatureId) {
|
|
753
|
+
this.activateFeature_(this.mapFeature_(featureId));
|
|
754
|
+
}
|
|
769
755
|
}
|
|
770
756
|
}
|
|
771
757
|
}
|
|
@@ -816,12 +802,8 @@ export class UserInteractions
|
|
|
816
802
|
if ('nerveId' in feature.properties) {
|
|
817
803
|
if (feature.properties.active) {
|
|
818
804
|
this.activateFeature_(feature);
|
|
819
|
-
} else {
|
|
820
|
-
tooltip = '';
|
|
821
|
-
}
|
|
822
|
-
if (feature.properties.nerveId !== feature.properties.featureId) {
|
|
823
|
-
this.activateNerveFeatures_(feature.properties.nerveId);
|
|
824
805
|
}
|
|
806
|
+
this.activateNerveFeatures_(feature.properties.nerveId);
|
|
825
807
|
} else {
|
|
826
808
|
this.activateFeature_(feature);
|
|
827
809
|
}
|
|
@@ -855,8 +837,8 @@ export class UserInteractions
|
|
|
855
837
|
}
|
|
856
838
|
}
|
|
857
839
|
|
|
858
|
-
selectionEvent_(
|
|
859
|
-
|
|
840
|
+
selectionEvent_(event, feature)
|
|
841
|
+
//=============================
|
|
860
842
|
{
|
|
861
843
|
const multipleSelect = event.ctrlKey || event.metaKey;
|
|
862
844
|
if (!multipleSelect) {
|
|
@@ -891,18 +873,29 @@ export class UserInteractions
|
|
|
891
873
|
//================
|
|
892
874
|
{
|
|
893
875
|
this.clearActiveMarker_();
|
|
894
|
-
const
|
|
895
|
-
|
|
876
|
+
const clickedFeature = this._map.queryRenderedFeatures(event.point)[0];
|
|
877
|
+
const originalEvent = event.originalEvent;
|
|
878
|
+
if (clickedFeature === undefined || this._activeFeatures.length === 1) {
|
|
879
|
+
this.selectionEvent_(originalEvent, clickedFeature);
|
|
880
|
+
} else if (this._activeFeatures.length > 1) {
|
|
881
|
+
const multipleSelect = originalEvent.ctrlKey || originalEvent.metaKey;
|
|
882
|
+
if (!multipleSelect) {
|
|
883
|
+
this.__unselectFeatures();
|
|
884
|
+
}
|
|
885
|
+
for (const feature of this._activeFeatures) {
|
|
886
|
+
this.selectFeature_(feature.id);
|
|
887
|
+
}
|
|
888
|
+
}
|
|
896
889
|
if (this._modal) {
|
|
897
890
|
// Remove tooltip, reset active features, etc
|
|
898
891
|
this.__resetFeatureDisplay();
|
|
899
892
|
this.__unselectFeatures();
|
|
900
893
|
this.__clearModal();
|
|
901
|
-
} else if (
|
|
894
|
+
} else if (clickedFeature !== undefined) {
|
|
902
895
|
this.__lastClickLngLat = event.lngLat;
|
|
903
|
-
this.__featureEvent('click',
|
|
904
|
-
if ('hyperlink' in
|
|
905
|
-
window.open(
|
|
896
|
+
this.__featureEvent('click', clickedFeature);
|
|
897
|
+
if ('properties' in clickedFeature && 'hyperlink' in clickedFeature.properties) {
|
|
898
|
+
window.open(clickedFeature.properties.hyperlink, '_blank');
|
|
906
899
|
}
|
|
907
900
|
}
|
|
908
901
|
}
|
|
@@ -915,6 +908,47 @@ export class UserInteractions
|
|
|
915
908
|
}
|
|
916
909
|
}
|
|
917
910
|
|
|
911
|
+
__enabledFeature(feature)
|
|
912
|
+
//=======================
|
|
913
|
+
{
|
|
914
|
+
const state = this._map.getFeatureState(feature);
|
|
915
|
+
return !(('hidden' in state && state.hidden));
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
enablePaths_(enable, event)
|
|
919
|
+
//=========================
|
|
920
|
+
{
|
|
921
|
+
this._contextMenu.hide();
|
|
922
|
+
const nodeId = event.target.getAttribute('featureId');
|
|
923
|
+
this.enablePathFeatures_(enable, this._pathways.pathFeatureIds(nodeId));
|
|
924
|
+
this.__clearModal();
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
enablePathFeatures_(enable, featureIds)
|
|
928
|
+
//=====================================
|
|
929
|
+
{
|
|
930
|
+
for (const featureId of featureIds) {
|
|
931
|
+
const feature = this.mapFeature_(featureId);
|
|
932
|
+
if (enable) {
|
|
933
|
+
this._map.removeFeatureState(feature, 'hidden');
|
|
934
|
+
} else {
|
|
935
|
+
this._map.setFeatureState(feature, { 'hidden': true });
|
|
936
|
+
this._disabledPathFeatures = true;
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
togglePaths()
|
|
942
|
+
//===========
|
|
943
|
+
{
|
|
944
|
+
if (this._disabledPathFeatures){
|
|
945
|
+
this.enablePathFeatures_(true, this._pathways.allFeatureIds());
|
|
946
|
+
this._disabledPathFeatures = false;
|
|
947
|
+
} else {
|
|
948
|
+
this.enablePathFeatures_(false, this._pathways.allFeatureIds());
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
|
|
918
952
|
enablePath(pathType, enable=true)
|
|
919
953
|
//===============================
|
|
920
954
|
{
|
package/src/styling.js
CHANGED
|
@@ -117,7 +117,6 @@ export class FeatureFillLayer extends VectorStyleLayer
|
|
|
117
117
|
const paintStyle = {
|
|
118
118
|
'fill-color': [
|
|
119
119
|
'case',
|
|
120
|
-
['boolean', ['feature-state', 'selected'], false], '#0F0',
|
|
121
120
|
['has', 'colour'], ['get', 'colour'],
|
|
122
121
|
['boolean', ['feature-state', 'active'], false], coloured ? '#D88' : '#CCC',
|
|
123
122
|
['any',
|
|
@@ -134,10 +133,10 @@ export class FeatureFillLayer extends VectorStyleLayer
|
|
|
134
133
|
['==', ['get', 'kind'], 'cell-type'],
|
|
135
134
|
], 0.1,
|
|
136
135
|
['has', 'node'], 0.3,
|
|
137
|
-
['boolean', ['feature-state', 'selected'], false], 1.0,
|
|
138
136
|
['boolean', ['feature-state', 'active'], false], 0.8,
|
|
137
|
+
['boolean', ['feature-state', 'selected'], false], 0.01,
|
|
139
138
|
['has', 'colour'], 0.008,
|
|
140
|
-
(coloured && !dimmed) ? 0.01 : 0.
|
|
139
|
+
(coloured && !dimmed) ? 0.01 : 0.1
|
|
141
140
|
]
|
|
142
141
|
};
|
|
143
142
|
return super.changedPaintStyle(paintStyle, changes);
|
|
@@ -198,18 +197,18 @@ export class FeatureBorderLayer extends VectorStyleLayer
|
|
|
198
197
|
}
|
|
199
198
|
lineOpacity.push(['boolean', ['feature-state', 'selected'], false]);
|
|
200
199
|
lineOpacity.push(0.9);
|
|
201
|
-
lineOpacity.push((outlined && !dimmed) ? 0.3 : 0.
|
|
200
|
+
lineOpacity.push((outlined && !dimmed) ? 0.3 : 0.1);
|
|
202
201
|
|
|
203
202
|
const lineWidth = [
|
|
204
203
|
'case',
|
|
205
204
|
['boolean', ['get', 'invisible'], false], 0.2,
|
|
206
205
|
];
|
|
206
|
+
lineWidth.push(['boolean', ['feature-state', 'selected'], false]);
|
|
207
|
+
lineWidth.push(2.5);
|
|
207
208
|
if (coloured && outlined) {
|
|
208
209
|
lineWidth.push(['boolean', ['feature-state', 'active'], false]);
|
|
209
210
|
lineWidth.push(1);
|
|
210
211
|
}
|
|
211
|
-
lineWidth.push(['boolean', ['feature-state', 'selected'], false]);
|
|
212
|
-
lineWidth.push(1.5);
|
|
213
212
|
lineWidth.push((coloured && outlined) ? 0.5 : 0.1);
|
|
214
213
|
|
|
215
214
|
return super.changedPaintStyle({
|
|
@@ -359,6 +358,8 @@ export class PathLineLayer extends VectorStyleLayer
|
|
|
359
358
|
'case',
|
|
360
359
|
['boolean', ['feature-state', 'hidden'], false], '#CCC',
|
|
361
360
|
['==', ['get', 'type'], 'bezier'], 'red',
|
|
361
|
+
['==', ['get', 'kind'], 'error'], '#FFFE0E',
|
|
362
|
+
['==', ['get', 'kind'], 'unknown'], '#FFC1DE',
|
|
362
363
|
['==', ['get', 'kind'], 'cns'], '#9B1FC1',
|
|
363
364
|
['==', ['get', 'kind'], 'lcn'], '#F19E38',
|
|
364
365
|
['==', ['get', 'kind'], 'para-post'], '#3F8F4A',
|
|
@@ -383,6 +384,8 @@ export class PathLineLayer extends VectorStyleLayer
|
|
|
383
384
|
'width', [
|
|
384
385
|
'case',
|
|
385
386
|
['==', ['get', 'type'], 'bezier'], 0.1,
|
|
387
|
+
['==', ['get', 'kind'], 'error'], 1,
|
|
388
|
+
['==', ['get', 'kind'], 'unknown'], 1,
|
|
386
389
|
['boolean', ['get', 'invisible'], false], 0.1,
|
|
387
390
|
['boolean', ['feature-state', 'selected'], false], 1.2,
|
|
388
391
|
['boolean', ['feature-state', 'active'], false], 0.9,
|
|
@@ -456,8 +459,7 @@ export class FeatureNerveLayer extends VectorStyleLayer
|
|
|
456
459
|
['boolean', ['feature-state', 'active'], false], '#222',
|
|
457
460
|
['boolean', ['feature-state', 'selected'], false], 'red',
|
|
458
461
|
['boolean', ['feature-state', 'hidden'], false], '#CCC',
|
|
459
|
-
|
|
460
|
-
'#FFF'
|
|
462
|
+
'#888'
|
|
461
463
|
],
|
|
462
464
|
'line-opacity': [
|
|
463
465
|
'case',
|