mapshaper 0.6.105 → 0.6.107

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.
@@ -1156,13 +1156,13 @@
1156
1156
  }
1157
1157
 
1158
1158
 
1159
- function adjustPointSymbolSizes(layers, overlayLyr, ext) {
1159
+ function calcDotScale(layers, ext) {
1160
1160
  var bbox = ext.getBounds().scale(1.3).toArray(); // add buffer
1161
1161
  // var topTier = 50000; // can be a bottleneck
1162
1162
  var topTier = 10000; // short-circuit counting here
1163
1163
  var count = 0;
1164
1164
  layers = layers.filter(function(lyr) {
1165
- return lyr.geometry_type == 'point' && lyr.gui.style.dotSize > 0;
1165
+ return lyr.geometry_type == 'point' && lyr.gui.style?.dotSize > 0;
1166
1166
  });
1167
1167
  layers.forEach(function(lyr) {
1168
1168
  count += countPoints(lyr.gui.displayLayer.shapes, topTier, bbox);
@@ -1180,17 +1180,10 @@
1180
1180
  k *= Math.pow(mapScale, 0.02);
1181
1181
  }
1182
1182
 
1183
-
1184
1183
  // scale down when map is small
1185
1184
  var smallSide = Math.min(ext.width(), ext.height());
1186
1185
  k *= utils$1.clamp(smallSide / 500, 0.5, 1);
1187
-
1188
- layers.forEach(function(lyr) {
1189
- lyr.gui.style.dotScale = k;
1190
- });
1191
- if (overlayLyr && overlayLyr.geometry_type == 'point' && overlayLyr.gui.style.dotSize > 0) {
1192
- overlayLyr.gui.style.dotScale = k;
1193
- }
1186
+ return k;
1194
1187
  }
1195
1188
 
1196
1189
  function countPoints(shapes, max, bbox) {
@@ -2754,349 +2747,6 @@
2754
2747
  return !!lyr?.gui.invertPoint;
2755
2748
  }
2756
2749
 
2757
- var darkStroke = "#334",
2758
- lightStroke = "#b7d9ea",
2759
- violet = "#cc6acc",
2760
- violetFill = "rgba(249, 120, 249, 0.20)",
2761
- gold = "#efc100",
2762
- black = "black",
2763
- grey = "#888",
2764
- selectionFill = "rgba(237, 214, 0, 0.12)",
2765
- hoverFill = "rgba(255, 120, 255, 0.12)",
2766
- activeStyle = { // outline style for the active layer
2767
- type: 'outline',
2768
- strokeColors: [lightStroke, darkStroke],
2769
- strokeWidth: 0.8,
2770
- dotColor: "#223",
2771
- dotSize: 1
2772
- },
2773
- activeStyleDarkMode = {
2774
- type: 'outline',
2775
- strokeColors: [lightStroke, 'white'],
2776
- strokeWidth: 0.9,
2777
- dotColor: 'white',
2778
- dotSize: 1
2779
- },
2780
- activeStyleForLabels = {
2781
- dotColor: "rgba(250, 0, 250, 0.45)", // violet dot with transparency
2782
- dotSize: 1
2783
- },
2784
- referenceStyle = { // outline style for reference layers
2785
- type: 'outline',
2786
- strokeColors: [null, '#78c110'], // upped saturation from #86c927
2787
- strokeWidth: 0.85,
2788
- dotColor: "#73ba20",
2789
- dotSize: 1
2790
- },
2791
- intersectionStyle = {
2792
- dotColor: "#F24400",
2793
- dotSize: 1
2794
- },
2795
- hoverStyles = {
2796
- polygon: {
2797
- fillColor: hoverFill,
2798
- strokeColor: black,
2799
- strokeWidth: 1.2
2800
- }, point: {
2801
- dotColor: violet, // black,
2802
- dotSize: 2.5
2803
- }, polyline: {
2804
- strokeColor: black,
2805
- strokeWidth: 2.5,
2806
- }
2807
- },
2808
- unselectedHoverStyles = {
2809
- polygon: {
2810
- fillColor: 'rgba(0,0,0,0)',
2811
- strokeColor: black,
2812
- strokeWidth: 1.2
2813
- }, point: {
2814
- dotColor: black, // grey,
2815
- dotSize: 2
2816
- }, polyline: {
2817
- strokeColor: black, // grey,
2818
- strokeWidth: 2.5
2819
- }
2820
- },
2821
- selectionStyles = {
2822
- polygon: {
2823
- fillColor: hoverFill,
2824
- strokeColor: black,
2825
- strokeWidth: 1.2
2826
- }, point: {
2827
- dotColor: violet, // black,
2828
- dotSize: 1.5
2829
- }, polyline: {
2830
- strokeColor: violet, // black,
2831
- strokeWidth: 2.5
2832
- }
2833
- },
2834
- // not used
2835
- selectionHoverStyles = {
2836
- polygon: {
2837
- fillColor: selectionFill,
2838
- strokeColor: black,
2839
- strokeWidth: 1.2
2840
- }, point: {
2841
- dotColor: black,
2842
- dotSize: 1.5
2843
- }, polyline: {
2844
- strokeColor: black,
2845
- strokeWidth: 2
2846
- }
2847
- },
2848
- pinnedStyles = {
2849
- polygon: {
2850
- fillColor: violetFill,
2851
- strokeColor: violet,
2852
- strokeWidth: 1.8
2853
- }, point: {
2854
- dotColor: violet,
2855
- dotSize: 3
2856
- }, polyline: {
2857
- strokeColor: violet, // black, // violet,
2858
- strokeWidth: 3
2859
- }
2860
- };
2861
-
2862
- function getIntersectionStyle(lyr, opts) {
2863
- return getDefaultStyle(lyr, intersectionStyle);
2864
- }
2865
-
2866
- // Display style for unselected layers with visibility turned on
2867
- // (may be fully styled or outlined)
2868
- function getReferenceLayerStyle(lyr, opts) {
2869
- var style;
2870
- if (layerHasCanvasDisplayStyle(lyr) && !opts.outlineMode) {
2871
- style = getCanvasDisplayStyle(lyr);
2872
- } else if (internal.layerHasLabels(lyr) && !opts.outlineMode) {
2873
- style = {dotSize: 0}; // no reference dots if labels are visible
2874
- } else {
2875
- style = getDefaultStyle(lyr, referenceStyle);
2876
- }
2877
- return style;
2878
- }
2879
-
2880
- function getActiveLayerStyle(lyr, opts) {
2881
- var style;
2882
- if (layerHasCanvasDisplayStyle(lyr) && !opts.outlineMode) {
2883
- style = getCanvasDisplayStyle(lyr);
2884
- } else if (internal.layerHasLabels(lyr) && !opts.outlineMode) {
2885
- style = getDefaultStyle(lyr, activeStyleForLabels);
2886
- } else if (opts.darkMode) {
2887
- style = getDefaultStyle(lyr, activeStyleDarkMode);
2888
- } else {
2889
- style = getDefaultStyle(lyr, activeStyle);
2890
- }
2891
- return style;
2892
- }
2893
-
2894
- // Returns a display style for the overlay layer.
2895
- // The overlay layer renders several kinds of feature, each of which is displayed
2896
- // with a different style.
2897
- //
2898
- // * hover shapes
2899
- // * selected shapes
2900
- // * pinned shapes
2901
- //
2902
- function getOverlayStyle(baseLyr, o, opts) {
2903
- if (opts.interactionMode == 'vertices') {
2904
- return getVertexStyle(baseLyr, o);
2905
- }
2906
- if (opts.interactionMode == 'edit_lines' ||
2907
- opts.interactionMode == 'edit_polygons') {
2908
- return getLineEditingStyle(o);
2909
- }
2910
- var geomType = baseLyr.geometry_type;
2911
- var topId = o.id; // pinned id (if pinned) or hover id
2912
- var topIdx = -1;
2913
- var styler = function(style, i) {
2914
- var defaultStyle = i === topIdx ? topStyle : outlineStyle;
2915
- if (baseStyle.styler) {
2916
- // TODO: render default stroke widths without scaling
2917
- // (will need to pass symbol scale to the styler function)
2918
- style.strokeWidth = defaultStyle.strokeWidth;
2919
- baseStyle.styler(style, i); // get styled stroke width (if set)
2920
- style.strokeColor = defaultStyle.strokeColor;
2921
- style.fillColor = defaultStyle.fillColor;
2922
- } else {
2923
- Object.assign(style, defaultStyle);
2924
- }
2925
- };
2926
- var baseStyle = getActiveLayerStyle(baseLyr, opts);
2927
- var outlineStyle = getDefaultStyle(baseLyr, selectionStyles[geomType]);
2928
- var topStyle;
2929
- var ids = o.ids.filter(function(i) {
2930
- return i != o.id; // move selected id to the end
2931
- });
2932
- if (o.id > -1) { // pinned or hover style
2933
- topStyle = getSelectedFeatureStyle(baseLyr, o, opts);
2934
- topIdx = ids.length;
2935
- ids.push(o.id); // put the pinned/hover feature last in the render order
2936
- }
2937
- var style = {
2938
- baseStyle: baseStyle,
2939
- styler,
2940
- ids,
2941
- overlay: true
2942
- };
2943
-
2944
- if (layerHasCanvasDisplayStyle(baseLyr) && !opts.outlineMode) {
2945
- if (geomType == 'point') {
2946
- style.styler = getOverlayPointStyler(getCanvasDisplayStyle(baseLyr).styler, styler);
2947
- }
2948
- style.type = 'styled';
2949
- }
2950
- return ids.length > 0 ? style : null;
2951
- }
2952
-
2953
-
2954
- function getDefaultStyle(lyr, baseStyle) {
2955
- return Object.assign({}, baseStyle);
2956
- }
2957
-
2958
-
2959
- // style for vertex edit mode
2960
- function getVertexStyle(lyr, o) {
2961
- return {
2962
- ids: o.ids,
2963
- overlay: true,
2964
- strokeColor: black,
2965
- strokeWidth: 1.5,
2966
- vertices: true,
2967
- vertex_overlay: o.hit_coordinates || null,
2968
- selected_points: o.selected_points || null,
2969
- fillColor: null
2970
- };
2971
- }
2972
-
2973
- // style for vertex edit mode
2974
- function getLineEditingStyle(o) {
2975
- return {
2976
- ids: o.ids,
2977
- overlay: true,
2978
- strokeColor: 'black',
2979
- strokeWidth: 1.2,
2980
- vertices: true,
2981
- vertex_overlay_color: o.hit_type == 'vertex' ? violet : black,
2982
- vertex_overlay_scale: o.hit_type == 'vertex' ? 2.5 : 2,
2983
- vertex_overlay: o.hit_coordinates || null,
2984
- selected_points: o.selected_points || null,
2985
- fillColor: null
2986
- };
2987
- }
2988
-
2989
-
2990
- function getSelectedFeatureStyle(lyr, o, opts) {
2991
- var isPinned = o.pinned;
2992
- var inSelection = o.ids.indexOf(o.id) > -1;
2993
- var geomType = lyr.geometry_type;
2994
- var style;
2995
- if (isPinned && opts.interactionMode == 'rectangles') {
2996
- // kludge for rectangle editing mode
2997
- style = selectionStyles[geomType];
2998
- } else if (isPinned) {
2999
- // a feature is pinned
3000
- style = pinnedStyles[geomType];
3001
- } else if (inSelection) {
3002
- // normal hover, or hover id is in the selection set
3003
- style = hoverStyles[geomType];
3004
- } else {
3005
- // features are selected, but hover id is not in the selection set
3006
- style = unselectedHoverStyles[geomType];
3007
- }
3008
- return getDefaultStyle(lyr, style);
3009
- }
3010
-
3011
- // Modify style to use scaled circle instead of dot symbol
3012
- function getOverlayPointStyler(baseStyler, overlayStyler) {
3013
- return function(obj, i) {
3014
- var dotColor;
3015
- var id = obj.ids ? obj.ids[i] : -1;
3016
- obj.strokeWidth = 0; // kludge to support setting minimum stroke width
3017
- baseStyler(obj, id);
3018
- if (overlayStyler) {
3019
- overlayStyler(obj, i);
3020
- }
3021
- dotColor = obj.dotColor;
3022
- if (obj.radius && dotColor) {
3023
- obj.radius += 0.4;
3024
- // delete obj.fillColor; // only show outline
3025
- obj.fillColor = dotColor; // comment out to only highlight stroke
3026
- obj.strokeColor = dotColor;
3027
- obj.strokeWidth = Math.max(obj.strokeWidth + 0.8, 1.5);
3028
- obj.opacity = 1;
3029
- }
3030
- };
3031
- }
3032
-
3033
- function getCanvasDisplayStyle(lyr) {
3034
- var styleIndex = {
3035
- opacity: 'opacity',
3036
- r: 'radius',
3037
- 'fill': 'fillColor',
3038
- 'fill-pattern': 'fillPattern',
3039
- 'fill-effect': 'fillEffect',
3040
- 'fill-opacity': 'fillOpacity',
3041
- 'stroke': 'strokeColor',
3042
- 'stroke-width': 'strokeWidth',
3043
- 'stroke-dasharray': 'lineDash',
3044
- 'stroke-opacity': 'strokeOpacity',
3045
- 'stroke-linecap': 'lineCap',
3046
- 'stroke-linejoin': 'lineJoin',
3047
- 'stroke-miterlimit': 'miterLimit'
3048
- },
3049
- // array of field names of relevant svg display properties
3050
- fields = getCanvasStyleFields(lyr).filter(function(f) {return f in styleIndex;}),
3051
- records = lyr.data.getRecords();
3052
-
3053
- var styler = function(style, i) {
3054
- var rec = records[i];
3055
- var fname, val;
3056
- for (var j=0; j<fields.length; j++) {
3057
- fname = fields[j];
3058
- val = rec && rec[fname];
3059
- if (val == 'none') {
3060
- val = 'transparent'; // canvas equivalent of CSS 'none'
3061
- }
3062
- // convert svg property name to mapshaper style equivalent
3063
- style[styleIndex[fname]] = val;
3064
- }
3065
-
3066
- if (style.strokeWidth && !style.strokeColor) {
3067
- style.strokeColor = 'black';
3068
- }
3069
- if (!('strokeWidth' in style) && style.strokeColor) {
3070
- style.strokeWidth = 1;
3071
- }
3072
- if (style.radius > 0 && !style.strokeWidth && !style.fillColor && lyr.geometry_type == 'point') {
3073
- style.fillColor = 'black';
3074
- }
3075
- };
3076
- var style = {styler: styler, type: 'styled'};
3077
- // use squares if radius is missing... (TODO: check behavior with labels, etc)
3078
- if (lyr.geometry_type == 'point' && fields.includes('r') === false) {
3079
- style.dotSize = 1;
3080
- }
3081
- return style;
3082
- }
3083
-
3084
- // check if layer should be displayed with a full style
3085
- function layerHasCanvasDisplayStyle(lyr) {
3086
- var fields = getCanvasStyleFields(lyr);
3087
- if (lyr.geometry_type == 'point') {
3088
- // return fields.indexOf('r') > -1; // require 'r' field for point symbols
3089
- return fields.includes('fill') || fields.includes('r'); // support colored squares
3090
- }
3091
- return utils$1.difference(fields, ['opacity', 'class']).length > 0;
3092
- }
3093
-
3094
-
3095
- function getCanvasStyleFields(lyr) {
3096
- var fields = lyr.data ? lyr.data.getFields() : [];
3097
- return internal.findPropertiesBySymbolGeom(fields, lyr.geometry_type);
3098
- }
3099
-
3100
2750
  // Create low-detail versions of large arc collections for faster rendering
3101
2751
  // at zoomed-out scales.
3102
2752
  function enhanceArcCollectionForDisplay(unfilteredArcs) {
@@ -3392,7 +3042,7 @@
3392
3042
  displayLayer: null,
3393
3043
  source: {dataset},
3394
3044
  bounds: null,
3395
- style: null,
3045
+ // style: null, // protect old style in projectLayerForDisplay()
3396
3046
  dynamic_crs: null,
3397
3047
  invertPoint: null,
3398
3048
  projectPoint: null
@@ -4559,18 +4209,20 @@
4559
4209
  model = gui.model,
4560
4210
  el = gui.container.findChild(".intersection-display"),
4561
4211
  readout = el.findChild(".intersection-count"),
4562
- checkBtn = el.findChild(".intersection-check"),
4563
4212
  repairBtn = el.findChild(".repair-btn"),
4213
+ optBox = gui.container.findChild('.intersections-opt'),
4564
4214
  _simplifiedXX, // saved simplified intersections, for repair
4565
- _unsimplifiedXX, // saved unsimplified intersection data, for performance
4566
- _disabled = false,
4567
- _on = false;
4568
-
4569
- el.findChild('.close-btn').on('click', dismissForever);
4215
+ _unsimplifiedXX; // saved unsimplified intersection data, for performance
4570
4216
 
4571
4217
  gui.on('simplify_drag_start', function() {
4572
- if (intersectionsAreOn()) {
4573
- hide();
4218
+ hide();
4219
+ });
4220
+
4221
+ gui.on('mode', updateRepairBtn);
4222
+
4223
+ gui.on('display_option_change', function(e) {
4224
+ if (e.option == 'intersectionsOn') {
4225
+ updateAsync();
4574
4226
  }
4575
4227
  });
4576
4228
 
@@ -4578,12 +4230,6 @@
4578
4230
  updateSync('simplify_drag_end');
4579
4231
  });
4580
4232
 
4581
- checkBtn.on('click', function() {
4582
- checkBtn.hide();
4583
- _on = true;
4584
- updateSync();
4585
- });
4586
-
4587
4233
  repairBtn.on('click', function() {
4588
4234
  var e = model.getActiveLayer();
4589
4235
  if (!_simplifiedXX || !e.dataset.arcs) return;
@@ -4595,59 +4241,46 @@
4595
4241
  });
4596
4242
 
4597
4243
  model.on('update', function(e) {
4598
- if (!intersectionsAreOn()) {
4599
- reset(); // need this?
4600
- return;
4601
- }
4602
4244
  var needRefresh = e.flags.simplify_method || e.flags.simplify ||
4603
- e.flags.repair || e.flags.clean;
4604
- if (needRefresh) {
4245
+ e.flags.repair || e.flags.clean || e.flags.select || intersectionsMayHaveChanged(e.flags);
4246
+ if (!intersectionsAreOn()) {
4247
+ reset();
4248
+ } else if (needRefresh) {
4605
4249
  updateAsync();
4606
4250
  } else if (e.flags.simplify_amount) {
4607
4251
  // slider is being dragged - hide readout and dots, retain data
4608
4252
  hide();
4609
- } else if (intersectionsMayHaveChanged(e.flags)) {
4610
- // intersections may have changed -- reset the display
4611
- reset();
4612
4253
  } else {
4613
4254
  // keep displaying the current intersections
4614
4255
  }
4615
4256
  });
4616
4257
 
4258
+ function updateRepairBtn() {
4259
+ if (intersectionsAreOn() && gui.getMode() == 'simplify' &&
4260
+ _simplifiedXX?.length > 0) {
4261
+ repairBtn.show();
4262
+ } else {
4263
+ repairBtn.hide();
4264
+ }
4265
+ }
4266
+
4617
4267
  function intersectionsAreOn() {
4618
- return _on && !_disabled;
4268
+ var e = model.getActiveLayer();
4269
+ return !!(gui.display.getOptions().intersectionsOn &&
4270
+ e && e.dataset.arcs && internal.layerHasPaths(e.layer));
4619
4271
  }
4620
4272
 
4621
- function turnOff() {
4273
+ function reset() {
4622
4274
  hide();
4623
- _on = false;
4624
4275
  _simplifiedXX = null;
4625
4276
  _unsimplifiedXX = null;
4626
4277
  }
4627
4278
 
4628
- function reset() {
4629
- turnOff();
4630
- if (_disabled) {
4631
- return;
4632
- }
4633
- var e = model.getActiveLayer();
4634
- if (!e) return;
4635
- if (internal.layerHasPaths(e.layer)) {
4636
- el.show();
4637
- checkBtn.show();
4638
- readout.hide();
4639
- repairBtn.hide();
4640
- }
4641
- }
4642
-
4643
- function dismissForever() {
4644
- _disabled = true;
4645
- turnOff();
4646
- }
4647
-
4648
4279
  function hide() {
4649
4280
  map.setIntersectionLayer(null);
4650
4281
  el.hide();
4282
+ repairBtn.hide();
4283
+ readout.hide();
4651
4284
  }
4652
4285
 
4653
4286
  // Update intersection display, after a short delay so map can redraw after previous
@@ -4657,16 +4290,16 @@
4657
4290
  }
4658
4291
 
4659
4292
  function updateSync(action) {
4660
- if (!intersectionsAreOn()) return;
4661
4293
  var e = model.getActiveLayer();
4662
4294
  var arcs = e.dataset && e.dataset.arcs;
4295
+ if (!intersectionsAreOn() || !arcs || !internal.layerHasPaths(e.layer)) {
4296
+ reset();
4297
+ return;
4298
+ }
4663
4299
  var intersectionOpts = {
4664
4300
  unique: true,
4665
4301
  tolerance: 0
4666
4302
  };
4667
- if (!arcs || !internal.layerHasPaths(e.layer)) {
4668
- return;
4669
- }
4670
4303
  if (arcs.getRetainedInterval() > 0) {
4671
4304
  // simplification
4672
4305
  _simplifiedXX = internal.findSegmentIntersections(arcs, intersectionOpts);
@@ -4686,7 +4319,6 @@
4686
4319
  var pointLyr, count = 0, html;
4687
4320
  el.show();
4688
4321
  readout.show();
4689
- checkBtn.hide();
4690
4322
  if (xx.length > 0) {
4691
4323
  pointLyr = internal.getIntersectionLayer(xx, lyr, arcs);
4692
4324
  count = internal.countPointsInLayer(pointLyr);
@@ -4699,12 +4331,7 @@
4699
4331
  html = utils$1.format('<span class="icon"></span>%s line intersection%s', count, utils$1.pluralSuffix(count));
4700
4332
  }
4701
4333
  readout.html(html);
4702
-
4703
- if (_simplifiedXX && count > 0) {
4704
- repairBtn.show();
4705
- } else {
4706
- repairBtn.hide();
4707
- }
4334
+ updateRepairBtn();
4708
4335
  }
4709
4336
  }
4710
4337
 
@@ -10356,16 +9983,221 @@
10356
9983
  if ((id > -1 || ids && ids.length > 0) && inspecting() && target && target) {
10357
9984
  _popup.show(id, ids, target, pin);
10358
9985
  } else {
10359
- _popup.hide();
9986
+ _popup.hide();
9987
+ }
9988
+ }
9989
+
9990
+ // does the attribute inspector appear on rollover
9991
+ function inspecting() {
9992
+ return gui.interaction && gui.interaction.modeUsesPopup(gui.interaction.getMode());
9993
+ }
9994
+
9995
+ return _self;
9996
+ }
9997
+
9998
+ var selectionFill = "rgba(237, 214, 0, 0.12)",
9999
+ // hoverFill = "rgba(255, 120, 255, 0.12)",
10000
+ hoverFill = "rgba(0, 0, 0, 0.08)",
10001
+ grey = "#888",
10002
+ violet = "#cc6acc",
10003
+ black = 'black',
10004
+ violetFill = "rgba(249, 120, 249, 0.25)",
10005
+ hoverStyles = {
10006
+ polygon: {
10007
+ fillColor: hoverFill,
10008
+ strokeColor: black,
10009
+ strokeWidth: 1.2
10010
+ }, point: {
10011
+ dotColor: black, // violet, // black,
10012
+ dotSize: 2.5
10013
+ }, polyline: {
10014
+ strokeColor: black,
10015
+ strokeWidth: 2,
10016
+ }
10017
+ },
10018
+ unselectedHoverStyles = {
10019
+ polygon: {
10020
+ fillColor: 'rgba(0,0,0,0)',
10021
+ strokeColor: black,
10022
+ strokeWidth: 1.2
10023
+ }, point: {
10024
+ dotColor: black, // grey,
10025
+ dotSize: 2
10026
+ }, polyline: {
10027
+ strokeColor: black, // grey,
10028
+ strokeWidth: 2.5
10029
+ }
10030
+ },
10031
+ selectionStyles = {
10032
+ polygon: {
10033
+ fillColor: hoverFill,
10034
+ strokeColor: black,
10035
+ strokeWidth: 1.2
10036
+ }, point: {
10037
+ dotColor: violet, // black,
10038
+ dotSize: 1.5
10039
+ }, polyline: {
10040
+ strokeColor: violet, // black,
10041
+ strokeWidth: 2.5
10042
+ }
10043
+ },
10044
+ // currently not used -- selection hover is not styled
10045
+ selectionHoverStyles = {
10046
+ polygon: {
10047
+ fillColor: selectionFill,
10048
+ strokeColor: black,
10049
+ strokeWidth: 1.2
10050
+ }, point: {
10051
+ dotColor: black,
10052
+ dotSize: 1.5
10053
+ }, polyline: {
10054
+ strokeColor: black,
10055
+ strokeWidth: 2
10056
+ }
10057
+ },
10058
+ pinnedStyles = {
10059
+ polygon: {
10060
+ fillColor: violetFill,
10061
+ strokeColor: violet,
10062
+ strokeWidth: 1.8
10063
+ }, point: {
10064
+ dotColor: violet,
10065
+ dotSize: 3
10066
+ }, polyline: {
10067
+ strokeColor: violet,
10068
+ strokeWidth: 2.4
10069
+ }
10070
+ };
10071
+
10072
+ function getOverlayLayers(activeLyr, hitData, styleOpts) {
10073
+ if (activeLyr?.hidden || !activeLyr?.gui?.style) return [];
10074
+ var displayLyr = activeLyr.gui.displayLayer;
10075
+ var layers, lyr, outlineStyle, ids;
10076
+ if (styleOpts.interactionMode == 'vertices') {
10077
+ // special overlay: vertex editing mode
10078
+ lyr = getOverlayLayer(activeLyr, hitData.ids);
10079
+ lyr.gui.style = getVertexStyle(hitData);
10080
+ return [lyr];
10081
+ }
10082
+ if (styleOpts.interactionMode == 'edit_lines' ||
10083
+ styleOpts.interactionMode == 'edit_polygons') {
10084
+ // special overlay: shape editing mode
10085
+ lyr = getOverlayLayer(activeLyr, hitData.ids);
10086
+ lyr.gui.style = getLineEditingStyle(hitData);
10087
+ return [lyr];
10088
+ }
10089
+ layers = [];
10090
+ // layer containing selected features, not including hover or pinned feature
10091
+ ids = utils$1.difference(hitData.ids || [], [hitData.id]);
10092
+ if (ids.length > 0) {
10093
+ lyr = getOverlayLayer(activeLyr, ids);
10094
+ outlineStyle = selectionStyles[displayLyr.geometry_type];
10095
+ lyr.gui.style = getOverlayStyle(activeLyr, ids, outlineStyle);
10096
+ layers.push(lyr);
10097
+ }
10098
+ // layer containing a single hover or pinned feature
10099
+ if (hitData.id > -1) {
10100
+ ids = [hitData.id];
10101
+ lyr = getOverlayLayer(activeLyr, ids);
10102
+ outlineStyle = getSelectedFeatureStyle(displayLyr, hitData, styleOpts);
10103
+ lyr.gui.style = getOverlayStyle(activeLyr, ids, outlineStyle);
10104
+ layers.push(lyr);
10105
+ }
10106
+ return layers;
10107
+ }
10108
+
10109
+ function getOverlayLayer(activeLyr, ids) {
10110
+ var displayLayer = filterLayerByIds(activeLyr.gui.displayLayer, ids);
10111
+ var gui = Object.assign({}, activeLyr.gui, {style: null, displayLayer});
10112
+ return Object.assign({}, activeLyr, {gui});
10113
+ }
10114
+
10115
+ function getOverlayStyle(baseLyr, ids, outlineStyle) {
10116
+ var geomType = baseLyr.gui.displayLayer.geometry_type;
10117
+ var baseStyle = baseLyr.gui.style;
10118
+ var baseStyler = baseStyle.styler || null;
10119
+ var styler = function(style, i) {
10120
+ if (!baseStyler) {
10121
+ // e.g. polygons in 'outline' mode
10122
+ Object.assign(style, outlineStyle);
10123
+ return;
10124
+ }
10125
+ var idx = ids[i];
10126
+ baseStyler(style, idx);
10127
+ if (geomType == 'point') {
10128
+ if (style.radius > 0) {
10129
+ style.radius += 0.8;
10130
+ if (style.strokeWidth > 0) {
10131
+ style.strokeColor = outlineStyle.dotColor;
10132
+ }
10133
+ }
10134
+ style.fillColor = outlineStyle.dotColor;
10135
+ } else {
10136
+ style.strokeColor = outlineStyle.strokeColor;
10137
+ style.fillColor = outlineStyle.fillColor;
10138
+ style.strokeWidth = Math.max(outlineStyle.strokeWidth, style.strokeWidth || 0);
10360
10139
  }
10140
+ style.opacity = 1;
10141
+ style.fillOpacity = 1;
10142
+ style.strokeOpacity = 1;
10143
+ };
10144
+ var style = Object.assign({}, baseStyle, {ids, overlay: true, type: 'styled', styler});
10145
+ if (baseStyle.dotSize > 0) {
10146
+ // dot size must be a static property (not applied by styler function)
10147
+ style.dotSize = outlineStyle.dotSize;
10361
10148
  }
10149
+ return style;
10150
+ }
10362
10151
 
10363
- // does the attribute inspector appear on rollover
10364
- function inspecting() {
10365
- return gui.interaction && gui.interaction.modeUsesPopup(gui.interaction.getMode());
10366
- }
10152
+ // style for vertex edit mode
10153
+ function getVertexStyle(o) {
10154
+ return {
10155
+ ids: o.ids,
10156
+ overlay: true,
10157
+ strokeColor: black,
10158
+ strokeWidth: 1.5,
10159
+ vertices: true,
10160
+ vertex_overlay: o.hit_coordinates || null,
10161
+ selected_points: o.selected_points || null,
10162
+ fillColor: null
10163
+ };
10164
+ }
10367
10165
 
10368
- return _self;
10166
+ // style for vertex edit mode
10167
+ function getLineEditingStyle(o) {
10168
+ return {
10169
+ ids: o.ids,
10170
+ overlay: true,
10171
+ strokeColor: black,
10172
+ strokeWidth: 1.2,
10173
+ vertices: true,
10174
+ vertex_overlay_color: o.hit_type == 'vertex' ? violet : black,
10175
+ vertex_overlay_scale: o.hit_type == 'vertex' ? 2.5 : 2,
10176
+ vertex_overlay: o.hit_coordinates || null,
10177
+ selected_points: o.selected_points || null,
10178
+ fillColor: null
10179
+ };
10180
+ }
10181
+
10182
+ function getSelectedFeatureStyle(lyr, o, opts) {
10183
+ var isPinned = o.pinned;
10184
+ var inSelection = o.ids.indexOf(o.id) > -1;
10185
+ var geomType = lyr.geometry_type;
10186
+ var style;
10187
+ if (isPinned && opts.interactionMode == 'rectangles') {
10188
+ // kludge for rectangle editing mode
10189
+ style = selectionStyles[geomType];
10190
+ } else if (isPinned) {
10191
+ // a feature is pinned
10192
+ style = pinnedStyles[geomType];
10193
+ } else if (inSelection) {
10194
+ // normal hover, or hover id is in the selection set
10195
+ style = hoverStyles[geomType];
10196
+ } else {
10197
+ // features are selected, but hover id is not in the selection set
10198
+ style = unselectedHoverStyles[geomType];
10199
+ }
10200
+ return Object.assign({}, style);
10369
10201
  }
10370
10202
 
10371
10203
  function isMultilineLabel(textNode) {
@@ -11399,6 +11231,146 @@
11399
11231
  initLineEditing(gui, ext, hit);
11400
11232
  }
11401
11233
 
11234
+ var darkStroke = "#334",
11235
+ lightStroke = "#b7d9ea",
11236
+ activeStyle = { // outline style for the active layer
11237
+ type: 'outline',
11238
+ strokeColors: [lightStroke, darkStroke],
11239
+ strokeWidth: 0.8,
11240
+ dotColor: "#223",
11241
+ dotSize: 1
11242
+ },
11243
+ activeStyleDarkMode = {
11244
+ type: 'outline',
11245
+ strokeColors: [lightStroke, 'white'],
11246
+ strokeWidth: 0.9,
11247
+ dotColor: 'white',
11248
+ dotSize: 1
11249
+ },
11250
+ activeStyleForLabels = {
11251
+ dotColor: "rgba(250, 0, 250, 0.45)", // violet dot with transparency
11252
+ dotSize: 1
11253
+ },
11254
+ referenceStyle = { // outline style for reference layers
11255
+ type: 'outline',
11256
+ strokeColors: [null, '#78c110'], // upped saturation from #86c927
11257
+ strokeWidth: 0.85,
11258
+ dotColor: "#73ba20",
11259
+ dotSize: 1
11260
+ },
11261
+ intersectionStyle = {
11262
+ dotColor: "#FF421D",
11263
+ dotSize: 1.3
11264
+ };
11265
+
11266
+ function getIntersectionStyle(lyr, opts) {
11267
+ return copyBaseStyle(intersectionStyle);
11268
+ }
11269
+
11270
+ // Display style for unselected layers with visibility turned on
11271
+ // (may be fully styled or outlined)
11272
+ function getReferenceLayerStyle(lyr, opts) {
11273
+ var style;
11274
+ if (layerHasDrawableStyle(lyr) && !opts.outlineMode) {
11275
+ // TODO: consider just copying lyr style
11276
+ style = getCanvasDisplayStyle(lyr);
11277
+ } else if (internal.layerHasLabels(lyr) && !opts.outlineMode) {
11278
+ style = {dotSize: 0}; // no reference dots if labels are visible
11279
+ } else {
11280
+ style = copyBaseStyle(referenceStyle);
11281
+ }
11282
+ return style;
11283
+ }
11284
+
11285
+ function getActiveLayerStyle(lyr, opts) {
11286
+ var style;
11287
+ if (layerHasDrawableStyle(lyr) && !opts.outlineMode) {
11288
+ style = getCanvasDisplayStyle(lyr);
11289
+ } else if (internal.layerHasLabels(lyr) && !opts.outlineMode) {
11290
+ style = copyBaseStyle(activeStyleForLabels);
11291
+ } else if (opts.darkMode) {
11292
+ style = copyBaseStyle(activeStyleDarkMode);
11293
+ } else {
11294
+ style = copyBaseStyle(activeStyle);
11295
+ }
11296
+ // kludge: no ghosted lines if not enabled
11297
+ if (style.strokeColors && !opts.ghostingOn) {
11298
+ style.strokeColors = [null, style.strokeColors[1]];
11299
+ }
11300
+
11301
+ return style;
11302
+ }
11303
+
11304
+ function copyBaseStyle(baseStyle) {
11305
+ return Object.assign({}, baseStyle);
11306
+ }
11307
+
11308
+ function getCanvasDisplayStyle(lyr) {
11309
+ var styleIndex = {
11310
+ opacity: 'opacity',
11311
+ r: 'radius',
11312
+ 'fill': 'fillColor',
11313
+ 'fill-pattern': 'fillPattern',
11314
+ 'fill-effect': 'fillEffect',
11315
+ 'fill-opacity': 'fillOpacity',
11316
+ 'stroke': 'strokeColor',
11317
+ 'stroke-width': 'strokeWidth',
11318
+ 'stroke-dasharray': 'lineDash',
11319
+ 'stroke-opacity': 'strokeOpacity',
11320
+ 'stroke-linecap': 'lineCap',
11321
+ 'stroke-linejoin': 'lineJoin',
11322
+ 'stroke-miterlimit': 'miterLimit'
11323
+ },
11324
+ // array of field names of relevant svg display properties
11325
+ fields = getStyleFields(lyr).filter(function(f) {return f in styleIndex;}),
11326
+ records = lyr.data.getRecords();
11327
+
11328
+ var styler = function(style, i) {
11329
+ var rec = records[i];
11330
+ var fname, val;
11331
+ for (var j=0; j<fields.length; j++) {
11332
+ fname = fields[j];
11333
+ val = rec && rec[fname];
11334
+ if (val == 'none') {
11335
+ val = 'transparent'; // canvas equivalent of CSS 'none'
11336
+ }
11337
+ // convert svg property name to mapshaper style equivalent
11338
+ style[styleIndex[fname]] = val;
11339
+ }
11340
+
11341
+ if (style.strokeWidth && !style.strokeColor) {
11342
+ style.strokeColor = 'black';
11343
+ }
11344
+ if (!('strokeWidth' in style) && style.strokeColor) {
11345
+ style.strokeWidth = 1;
11346
+ }
11347
+ if (style.radius > 0 && !style.strokeWidth && !style.fillColor && lyr.geometry_type == 'point') {
11348
+ style.fillColor = 'black';
11349
+ }
11350
+ };
11351
+ var style = {styler: styler, type: 'styled'};
11352
+ // use squares if radius is missing... (TODO: check behavior with labels, etc)
11353
+ if (lyr.geometry_type == 'point' && fields.includes('r') === false) {
11354
+ style.dotSize = 1;
11355
+ }
11356
+ return style;
11357
+ }
11358
+
11359
+ // check if layer should be displayed with a full style
11360
+ function layerHasDrawableStyle(lyr) {
11361
+ var fields = getStyleFields(lyr);
11362
+ if (lyr.geometry_type == 'point') {
11363
+ // return fields.indexOf('r') > -1; // require 'r' field for point symbols
11364
+ return fields.includes('fill') || fields.includes('r'); // support colored squares
11365
+ }
11366
+ return utils$1.difference(fields, ['opacity', 'class']).length > 0;
11367
+ }
11368
+
11369
+ function getStyleFields(lyr) {
11370
+ var fields = lyr.data ? lyr.data.getFields() : [];
11371
+ return internal.findStylePropertiesBySymbolGeom(fields, lyr.geometry_type);
11372
+ }
11373
+
11402
11374
  function MapExtent(_position) {
11403
11375
  var _scale = 1,
11404
11376
  _cx, _cy, // center in geographic units
@@ -11790,22 +11762,23 @@
11790
11762
  var arcs;
11791
11763
  var style = lyr.gui.style;
11792
11764
  var arcCounts = lyr.gui.arcCounts;
11793
- var darkStyle = {strokeWidth: style.strokeWidth, strokeColor: style.strokeColors[1]},
11794
- lightStyle = {strokeWidth: style.strokeWidth, strokeColor: style.strokeColors[0]};
11765
+ var fgStyle = {strokeWidth: style.strokeWidth, strokeColor: style.strokeColors[1]},
11766
+ bgStyle = {strokeWidth: style.strokeWidth, strokeColor: style.strokeColors[0]};
11795
11767
  var filter;
11768
+
11796
11769
  if (internal.layerHasPaths(lyr.gui.displayLayer)) {
11797
11770
  if (!arcCounts) {
11798
11771
  arcCounts = lyr.gui.arcCounts = new Uint8Array(lyr.gui.displayArcs.size());
11799
11772
  internal.countArcsInShapes(lyr.gui.displayLayer.shapes, arcCounts);
11800
11773
  }
11801
11774
  arcs = getArcsForRendering(lyr, ext);
11802
- if (lightStyle.strokeColor) {
11775
+ if (bgStyle.strokeColor) {
11803
11776
  filter = getArcFilter(arcs, ext, false, arcCounts);
11804
- canv.drawArcs(arcs, lightStyle, filter);
11777
+ canv.drawArcs(arcs, bgStyle, filter);
11805
11778
  }
11806
- if (darkStyle.strokeColor && lyr.gui.displayLayer.geometry_type != 'point') {
11779
+ if (fgStyle.strokeColor && lyr.gui.displayLayer.geometry_type != 'point') {
11807
11780
  filter = getArcFilter(arcs, ext, true, arcCounts);
11808
- canv.drawArcs(arcs, darkStyle, filter);
11781
+ canv.drawArcs(arcs, fgStyle, filter);
11809
11782
  }
11810
11783
  }
11811
11784
  if (lyr.gui.displayLayer.geometry_type == 'point') {
@@ -12206,10 +12179,10 @@
12206
12179
  var scale = style.dotScale || 1;
12207
12180
  size += (scale - 1) / 2;
12208
12181
  size *= Math.pow(scale, 0.3);
12209
-
12210
12182
  // shrink dots slightly on retina displays, to adjust for greater clarity
12211
- // and reduce number of pixels to draw on large datasets.
12212
- return Math.round(Math.pow(GUI.getPixelRatio(), 0.8) * size);
12183
+ // and to reduce number of pixels to draw on large datasets.
12184
+ size *= Math.pow(GUI.getPixelRatio(), 0.8);
12185
+ return Math.round(size);
12213
12186
  }
12214
12187
 
12215
12188
  function getScaledTransform(ext) {
@@ -12526,14 +12499,18 @@
12526
12499
  // is noticeably slower during animations with multiple canvases.
12527
12500
  // Highlights are drawn on a separate canvas while hovering, because this
12528
12501
  // is generally faster than redrawing all of the shapes.
12529
- this.drawOverlayLayer = function(lyr, action) {
12530
- if (action == 'hover' && lyr) {
12502
+ this.drawOverlayLayers = function(layers, action) {
12503
+ var canv;
12504
+ if (action == 'hover') {
12505
+ canv = _overlayCanv;
12531
12506
  _overlayCanv.prep(_ext);
12532
- drawCanvasLayer(lyr, _overlayCanv);
12533
12507
  } else {
12508
+ canv = _mainCanv;
12534
12509
  _overlayCanv.hide();
12535
- drawCanvasLayer(lyr, _mainCanv);
12536
12510
  }
12511
+ layers.forEach(function(lyr) {
12512
+ drawCanvasLayer(lyr, canv);
12513
+ });
12537
12514
  };
12538
12515
 
12539
12516
  this.drawFurnitureLayers = function(layers, action) {
@@ -12845,14 +12822,14 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
12845
12822
  _ext = new MapExtent(position),
12846
12823
  _visibleLayers = [], // cached visible map layers
12847
12824
  _hit, _nav,
12848
- _intersectionLyr, _activeLyr, _overlayLyr,
12825
+ _intersectionLyr, _activeLyr, _overlayLayers,
12849
12826
  _renderer, _dynamicCRS;
12850
12827
 
12851
12828
  _mouse.disable(); // wait for gui.focus() to activate mouse events
12852
12829
 
12853
12830
  model.on('select', function(e) {
12854
12831
  _intersectionLyr = null;
12855
- _overlayLyr = null;
12832
+ // _overlayLyr = null;
12856
12833
  });
12857
12834
 
12858
12835
  gui.on('active', function() {
@@ -12880,8 +12857,8 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
12880
12857
  if (lyr == _intersectionLyr) return; // no change
12881
12858
  if (lyr) {
12882
12859
  enhanceLayerForDisplay(lyr, dataset, getDisplayOptions());
12860
+ lyr.gui.style = getIntersectionStyle(lyr.gui.displayLayer, getGlobalStyleOptions());
12883
12861
  _intersectionLyr = lyr;
12884
- _intersectionLyr.gui.style = getIntersectionStyle(_intersectionLyr.gui.displayLayer, getGlobalStyleOptions());
12885
12862
  } else {
12886
12863
  _intersectionLyr = null;
12887
12864
  }
@@ -12909,16 +12886,6 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
12909
12886
  return p1 && p2 ? formatCoordsForDisplay(p1, p2) : null;
12910
12887
  };
12911
12888
 
12912
- // this.getCenterLngLat = function() {
12913
- // var bounds = _ext.getBounds();
12914
- // var crs = this.getDisplayCRS();
12915
- // // TODO: handle case where active layer is a frame layer
12916
- // if (!bounds.hasBounds() || !crs) {
12917
- // return null;
12918
- // }
12919
- // return internal.toLngLat([bounds.centerX(), bounds.centerY()], crs);
12920
- // };
12921
-
12922
12889
  this.getDisplayCRS = function() {
12923
12890
  if (!_activeLyr) {
12924
12891
  return _dynamicCRS || internal.parseCrsString('wgs84');
@@ -12974,13 +12941,10 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
12974
12941
  clearAllDisplayArcs();
12975
12942
 
12976
12943
  // Reproject all visible map layers
12977
- getContentLayers().forEach(function(lyr) {
12944
+ getContentLayers().concat(_intersectionLyr || []).forEach(function(lyr) {
12978
12945
  projectLayerForDisplay(lyr, newCRS);
12979
12946
  });
12980
12947
 
12981
- // kludge to make sure all layers have styles
12982
- updateLayerStyles(getContentLayers());
12983
-
12984
12948
  // Update map extent (also triggers redraw)
12985
12949
  projectMapExtent(_ext, oldCRS, this.getDisplayCRS(), calcFullBounds());
12986
12950
  updateFullBounds();
@@ -13001,7 +12965,7 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
13001
12965
  new BoxTool(gui, _ext, _nav),
13002
12966
  new RectangleControl(gui, _hit),
13003
12967
  initInteractiveEditing(gui, _ext, _hit);
13004
- _hit.on('change', updateOverlayLayer);
12968
+ _hit.on('change', function() { drawLayers('hover'); });
13005
12969
  }
13006
12970
 
13007
12971
  _ext.on('change', function(e) {
@@ -13020,7 +12984,7 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
13020
12984
  darkMode: !!gui.state.dark_basemap,
13021
12985
  outlineMode: mode == 'vertices',
13022
12986
  interactionMode: mode
13023
- }, opts);
12987
+ }, opts, gui.display.getOptions()); // intersectionsOn, ghostingOn
13024
12988
  }
13025
12989
 
13026
12990
  // Refresh map display in response to data changes, layer selection, etc.
@@ -13029,9 +12993,6 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
13029
12993
  var prevLyr = _activeLyr || null;
13030
12994
  var fullBounds;
13031
12995
  var needReset;
13032
- if (!prevLyr) {
13033
- // initMap(); // first call
13034
- }
13035
12996
 
13036
12997
  if (arcsMayHaveChanged(e.flags)) {
13037
12998
  // regenerate filtered arcs the next time they are needed for rendering
@@ -13056,7 +13017,9 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
13056
13017
 
13057
13018
  if (updated.layer) {
13058
13019
  _activeLyr = updated.layer;
13059
- initActiveLayer();
13020
+ enhanceLayerForDisplay(_activeLyr, updated.dataset, getDisplayOptions());
13021
+ // need to set layer style so hit detection can calculate size of certain symbols
13022
+ _activeLyr.gui.style = getActiveLayerStyle(_activeLyr.gui.displayLayer, getGlobalStyleOptions());
13060
13023
  } else {
13061
13024
  _activeLyr = null;
13062
13025
  }
@@ -13092,23 +13055,6 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
13092
13055
  map.dispatchEvent('updated');
13093
13056
  }
13094
13057
 
13095
-
13096
- function updateOverlayLayer(e) {
13097
- var style = !_activeLyr?.gui?.style ? null :
13098
- getOverlayStyle(_activeLyr.gui.displayLayer, e, getGlobalStyleOptions());
13099
- if (style) {
13100
- var displayLayer = filterLayerByIds(_activeLyr.gui.displayLayer, style.ids);
13101
- var gui = Object.assign({}, _activeLyr.gui, {style, displayLayer});
13102
- style.dotScale = _activeLyr.gui.style.dotScale;
13103
- _overlayLyr = utils$1.defaults({gui}, _activeLyr);
13104
- } else {
13105
- _overlayLyr = null;
13106
- }
13107
-
13108
- // 'hover' avoids redrawing all svg symbols when only highlight needs to refresh
13109
- drawLayers('hover');
13110
- }
13111
-
13112
13058
  function getDisplayOptions() {
13113
13059
  return {
13114
13060
  crs: _dynamicCRS
@@ -13243,12 +13189,6 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
13243
13189
  });
13244
13190
  }
13245
13191
 
13246
- function initActiveLayer() {
13247
- var active = model.getActiveLayer();
13248
- enhanceLayerForDisplay(active.layer, active.dataset, getDisplayOptions());
13249
- active.layer.gui.style = getActiveLayerStyle(active.layer.gui.displayLayer, getGlobalStyleOptions());
13250
- }
13251
-
13252
13192
  function getDrawableFurnitureLayers(layers) {
13253
13193
  if (!isPreviewView()) return [];
13254
13194
  return getVisibleMapLayers().filter(function(o) {
@@ -13263,14 +13203,13 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
13263
13203
  // regenerating active style everytime, to support style change when
13264
13204
  // switching between outline and preview modes.
13265
13205
  style = getActiveLayerStyle(mapLayer.gui.displayLayer, getGlobalStyleOptions());
13266
- if (style.type != 'styled' && layers.length > 1 && style.strokeColors) {
13267
- // kludge to hide ghosted layers when reference layers are present
13268
- // TODO: consider never showing ghosted layers (which appear after
13269
- // commands like dissolve and filter).
13270
- style = utils$1.defaults({
13271
- strokeColors: [null, style.strokeColors[1]]
13272
- }, style);
13273
- }
13206
+ // changed: ghosting is set in gui-layer-styler.mjs
13207
+ // if (style.type != 'styled' && layers.length > 1 && style.strokeColors) {
13208
+ // // kludge to hide ghosted layers when reference layers are present
13209
+ // style = utils.defaults({
13210
+ // strokeColors: [null, style.strokeColors[1]]
13211
+ // }, style);
13212
+ // }
13274
13213
  } else {
13275
13214
  if (mapLayer == _activeLyr) {
13276
13215
  console.error("Error: shared map layer");
@@ -13331,14 +13270,25 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
13331
13270
  contentLayers = contentLayers.concat(_intersectionLyr);
13332
13271
  }
13333
13272
  // moved this below intersection layer addition, so intersection dots get scaled
13334
- adjustPointSymbolSizes(contentLayers, _overlayLyr, _ext);
13273
+
13274
+ // Adjust dot size based on total visible dots TODO: move this
13275
+ var dotScale = calcDotScale(contentLayers, _ext);
13276
+ contentLayers.forEach(function(lyr) {
13277
+ lyr.gui.style.dotScale = dotScale;
13278
+ });
13335
13279
 
13336
13280
  // RENDERING
13337
13281
  // draw main content layers
13338
13282
  _renderer.drawMainLayers(contentLayers, action);
13283
+
13339
13284
  // draw hover & selection overlay
13340
- _renderer.drawOverlayLayer(_overlayLyr, action);
13341
- // draw furniture
13285
+ if (!_overlayLayers || action != 'nav') {
13286
+ // cache layers to use when panning/zooming
13287
+ _overlayLayers = getOverlayLayers(_activeLyr, _hit.getHitState(), getGlobalStyleOptions());
13288
+ }
13289
+ _renderer.drawOverlayLayers(_overlayLayers, action);
13290
+
13291
+ // TODO: draw furniture
13342
13292
  // _renderer.drawFurnitureLayers(furnitureLayers, action);
13343
13293
  gui.dispatchEvent('map_rendered');
13344
13294
  }
@@ -13395,14 +13345,12 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
13395
13345
  }
13396
13346
 
13397
13347
  function Basemap(gui) {
13398
- var menu = gui.container.findChild('.basemap-options');
13348
+ var menu = gui.container.findChild('.display-options');
13399
13349
  var fadeBtn = new SimpleButton(menu.findChild('.fade-btn'));
13400
- var closeBtn = new SimpleButton(menu.findChild('.close2-btn'));
13401
13350
  var clearBtn = new SimpleButton(menu.findChild('.clear-btn'));
13402
13351
  var menuButtons = menu.findChild('.basemap-styles');
13403
13352
  var overlayButtons = gui.container.findChild('.basemap-overlay-buttons');
13404
13353
  var container = gui.container.findChild('.basemap-container');
13405
- var basemapBtn = gui.container.findChild('.basemap-btn');
13406
13354
  var basemapNote = gui.container.findChild('.basemap-note');
13407
13355
  var basemapWarning = gui.container.findChild('.basemap-warning');
13408
13356
  var mapEl = gui.container.findChild('.basemap');
@@ -13417,22 +13365,25 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
13417
13365
  // TODO: check page URL for compatibility with mapbox key
13418
13366
  init();
13419
13367
  } else {
13420
- basemapBtn.hide();
13368
+ menu.findChild('.basemap-opts').hide();
13421
13369
  }
13422
13370
 
13423
13371
  function init() {
13424
- gui.addMode('basemap', turnOn, turnOff, basemapBtn);
13425
-
13426
- closeBtn.on('click', function() {
13427
- gui.clearMode();
13428
- turnOff();
13372
+ gui.on('mode', function(e) {
13373
+ if (e.prev == 'display_options') {
13374
+ basemapWarning.hide();
13375
+ basemapNote.hide();
13376
+ }
13377
+ if (e.name == 'display_options') {
13378
+ onUpdate();
13379
+ }
13429
13380
  });
13430
13381
 
13431
13382
  clearBtn.on('click', function() {
13432
13383
  if (activeStyle) {
13433
13384
  turnOffBasemap();
13434
13385
  updateButtons();
13435
- closeMenu();
13386
+ // closeMenu();
13436
13387
  }
13437
13388
  });
13438
13389
 
@@ -13473,7 +13424,7 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
13473
13424
  showBasemap(style);
13474
13425
  }
13475
13426
  updateButtons();
13476
- closeMenu();
13427
+ // closeMenu();
13477
13428
  }
13478
13429
  });
13479
13430
  }
@@ -13513,11 +13464,6 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
13513
13464
  });
13514
13465
  }
13515
13466
 
13516
- function turnOn() {
13517
- onUpdate();
13518
- menu.show();
13519
- }
13520
-
13521
13467
  function onUpdate() {
13522
13468
  var activeLyr = gui.model.getActiveLayer(); // may be null
13523
13469
  var info = getDatasetCrsInfo(activeLyr?.dataset); // defaults to wgs84
@@ -13539,19 +13485,13 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
13539
13485
  activeStyle = null;
13540
13486
  updateButtons();
13541
13487
  } else {
13542
- note = `Your data ${activeStyle ? 'is' : 'will be'} displayed using the Mercator projection.`;
13488
+ note = `Note: basemaps use the Mercator projection.`;
13543
13489
  basemapNote.text(note).show();
13544
13490
  overlayButtons.show();
13545
13491
  overlayButtons.removeClass('disabled');
13546
13492
  }
13547
13493
  }
13548
13494
 
13549
- function turnOff() {
13550
- basemapWarning.hide();
13551
- basemapNote.hide();
13552
- menu.hide();
13553
- }
13554
-
13555
13495
  function enabled() {
13556
13496
  return !!(mapEl && params);
13557
13497
  }
@@ -13667,6 +13607,64 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
13667
13607
  return {refresh, show: onUpdate};
13668
13608
  }
13669
13609
 
13610
+ function DisplayOptions(gui) {
13611
+ var menuBtn = gui.container.findChild('.display-btn');
13612
+ var menu = gui.container.findChild('.display-options');
13613
+ var closeBtn = new SimpleButton(menu.findChild('.close2-btn'));
13614
+ var xxBox = menu.findChild('.intersections-opt');
13615
+ var ghostBox = menu.findChild('.ghost-opt');
13616
+
13617
+ var savedOpts = GUI.getSavedValue('display_options') || {};
13618
+ xxBox.node().checked = savedOpts.intersectionsOn;
13619
+ ghostBox.node().checked = savedOpts.ghostingOn;
13620
+
13621
+
13622
+ gui.addMode('display_options', turnOn, turnOff, menuBtn);
13623
+
13624
+ closeBtn.on('click', function() {
13625
+ gui.clearMode();
13626
+ turnOff();
13627
+ });
13628
+
13629
+ gui.on('display_option_change', function() {
13630
+ GUI.setSavedValue('display_options', getOptions());
13631
+ });
13632
+
13633
+ xxBox.on('change', function() {
13634
+ gui.dispatchEvent('display_option_change', {
13635
+ option: 'intersectionsOn',
13636
+ value: getOptions().intersectionsOn
13637
+ });
13638
+ });
13639
+
13640
+ ghostBox.on('change', function() {
13641
+ gui.dispatchEvent('display_option_change', {
13642
+ option: 'ghostingOn',
13643
+ value: getOptions().ghostingOn
13644
+ });
13645
+ gui.dispatchEvent('map-needs-refresh');
13646
+ });
13647
+
13648
+ function getOptions() {
13649
+ return {
13650
+ intersectionsOn: xxBox.node().checked,
13651
+ ghostingOn: ghostBox.node().checked
13652
+ };
13653
+ }
13654
+
13655
+ function turnOn() {
13656
+ menu.show();
13657
+ }
13658
+
13659
+ function turnOff() {
13660
+ menu.hide();
13661
+ }
13662
+
13663
+ return {
13664
+ getOptions
13665
+ };
13666
+ }
13667
+
13670
13668
  function GuiInstance(container, opts) {
13671
13669
  var gui = new ModeSwitcher();
13672
13670
  opts = utils$1.extend({
@@ -13684,12 +13682,14 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
13684
13682
  gui.model = new Model(gui);
13685
13683
  gui.keyboard = new KeyboardEvents(gui);
13686
13684
  gui.buttons = new SidebarButtons(gui);
13685
+ gui.display = new DisplayOptions(gui);
13687
13686
  gui.basemap = new Basemap(gui);
13688
13687
  gui.session = new SessionHistory(gui);
13689
13688
  gui.contextMenu = new ContextMenu();
13690
13689
  gui.undo = new Undo(gui);
13691
13690
  gui.map = new MshpMap(gui);
13692
13691
 
13692
+
13693
13693
  gui.state = {};
13694
13694
 
13695
13695
  var msgCount = 0;