mapshaper 0.6.67 → 0.6.69

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.
@@ -2417,7 +2417,7 @@
2417
2417
  // Show a popup error message, then throw an error
2418
2418
  var msg = GUI.formatMessageArgs(arguments);
2419
2419
  gui.alert(msg);
2420
- throw new Error(msg);
2420
+ throw new internal.UserError(msg);
2421
2421
  }
2422
2422
 
2423
2423
  function error() {
@@ -3882,7 +3882,11 @@
3882
3882
  } else {
3883
3883
  // stack seems to change if Error is logged directly
3884
3884
  console.error(err.stack);
3885
- gui.alert('Export failed for an unknown reason');
3885
+ var msg = 'Export failed for an unknown reason';
3886
+ if (err.name == 'UserError') {
3887
+ msg = err.message;
3888
+ }
3889
+ gui.alert(msg, 'Export failed');
3886
3890
  }
3887
3891
  }).finally(function() {
3888
3892
  gui.clearProgressMessage();
@@ -7820,6 +7824,7 @@
7820
7824
  function onMouseUp(e) {
7821
7825
  var evt = procMouseEvent(e),
7822
7826
  elapsed, dx, dy;
7827
+ _self.dispatchEvent('mouseup', evt);
7823
7828
  if (_dragging) {
7824
7829
  stopDragging(evt);
7825
7830
  }
@@ -7847,6 +7852,7 @@
7847
7852
 
7848
7853
  function onMouseMove(e) {
7849
7854
  var evt = procMouseEvent(e);
7855
+ _self.dispatchEvent('mousemove', evt);
7850
7856
  if (!_dragging && _downEvt && _downEvt.hover) {
7851
7857
  _dragging = true;
7852
7858
  _self.dispatchEvent('dragstart', evt);
@@ -7969,37 +7975,21 @@
7969
7975
  });
7970
7976
  });
7971
7977
 
7972
- document.addEventListener('mousemove', function(e) {
7978
+ gui.map.getMouse().on('mousemove', function(e) {
7973
7979
  if (!_on || !activeHandle || !prevXY || !boxCoords || !_visible) return;
7974
7980
  var xy = {x: e.pageX, y: e.pageY};
7975
- var scale = gui.map.getExtent().getPixelSize();
7976
- var dx = (xy.x - prevXY.x) * scale;
7977
- var dy = -(xy.y - prevXY.y) * scale;
7978
- var shifting = activeHandle.col == 'center' && activeHandle.row == 'center';
7979
- var centered = gui.keyboard.shiftIsPressed() && !shifting;
7980
- if (activeHandle.col == 'left' || shifting) {
7981
- boxCoords[0] += dx;
7982
- if (centered) boxCoords[2] -= dx;
7983
- }
7984
- if (activeHandle.col == 'right' || shifting) {
7985
- boxCoords[2] += dx;
7986
- if (centered) boxCoords[0] -= dx;
7987
- }
7988
- if (activeHandle.row == 'top' || shifting) {
7989
- boxCoords[3] += dy;
7990
- if (centered) boxCoords[1] -= dy;
7991
- }
7992
- if (activeHandle.row == 'bottom' || shifting) {
7993
- boxCoords[1] += dy;
7994
- if (centered) boxCoords[3] -= dy;
7981
+ var scaling = gui.keyboard.shiftIsPressed() && activeHandle.type == 'corner';
7982
+ if (scaling) {
7983
+ rescaleBox(e.x, e.y);
7984
+ } else {
7985
+ resizeBox(xy.x - prevXY.x, xy.y - prevXY.y, activeHandle);
7995
7986
  }
7996
-
7997
7987
  prevXY = xy;
7998
7988
  redraw();
7999
7989
  box.dispatchEvent('handle_drag');
8000
7990
  });
8001
7991
 
8002
- document.addEventListener('mouseup', function() {
7992
+ gui.map.getMouse().on('mouseup', function(e) {
8003
7993
  if (activeHandle && _on) {
8004
7994
  activeHandle.el.css('background', null);
8005
7995
  activeHandle = null;
@@ -8012,6 +8002,43 @@
8012
8002
  });
8013
8003
  }
8014
8004
 
8005
+ function resizeBox(dx, dy, activeHandle) {
8006
+ var shifting = activeHandle.type == 'center';
8007
+ var centered = gui.keyboard.shiftIsPressed() && activeHandle.type == 'edge';
8008
+ var scale = gui.map.getExtent().getPixelSize();
8009
+ dx *= scale;
8010
+ dy *= -scale;
8011
+
8012
+ if (activeHandle.col == 'left' || shifting) {
8013
+ boxCoords[0] += dx;
8014
+ if (centered) boxCoords[2] -= dx;
8015
+ }
8016
+ if (activeHandle.col == 'right' || shifting) {
8017
+ boxCoords[2] += dx;
8018
+ if (centered) boxCoords[0] -= dx;
8019
+ }
8020
+ if (activeHandle.row == 'top' || shifting) {
8021
+ boxCoords[3] += dy;
8022
+ if (centered) boxCoords[1] -= dy;
8023
+ }
8024
+ if (activeHandle.row == 'bottom' || shifting) {
8025
+ boxCoords[1] += dy;
8026
+ if (centered) boxCoords[3] -= dy;
8027
+ }
8028
+ }
8029
+
8030
+ function rescaleBox(x, y) {
8031
+ var p = gui.map.getExtent().translatePixelCoords(x, y);
8032
+ var cx = (boxCoords[0] + boxCoords[2])/2;
8033
+ var cy = (boxCoords[1] + boxCoords[3])/2;
8034
+ var dist2 = geom.distance2D(cx, cy, p[0], p[1]);
8035
+ var dist = geom.distance2D(cx, cy, boxCoords[0], boxCoords[1]);
8036
+ var k = dist2 / dist;
8037
+ var dx = (boxCoords[2] - cx) * k;
8038
+ var dy = (boxCoords[3] - cy) * k;
8039
+ boxCoords = [cx - dx, cy - dy, cx + dx, cy + dy];
8040
+ }
8041
+
8015
8042
  box.setDataCoords = function(bbox) {
8016
8043
  boxCoords = bbox;
8017
8044
  redraw();
@@ -8107,8 +8134,10 @@
8107
8134
  // if (i == 4) continue; // skip middle handle
8108
8135
  var c = Math.floor(i / 3);
8109
8136
  var r = i % 3;
8137
+ var type = i == 4 && 'center' || c != 1 && r != 1 && 'corner' || 'edge';
8110
8138
  handles.push({
8111
8139
  el: El('div').addClass('handle').appendTo(el),
8140
+ type: type,
8112
8141
  col: c == 0 && 'left' || c == 1 && 'center' || 'right',
8113
8142
  row: r == 0 && 'top' || r == 1 && 'center' || 'bottom'
8114
8143
  });
@@ -8802,11 +8831,11 @@
8802
8831
  return textNode.childNodes.length > 1;
8803
8832
  }
8804
8833
 
8805
- function toggleTextAlign(textNode, rec) {
8806
- var curr = rec['text-anchor'] || 'middle';
8807
- var value = curr == 'middle' && 'start' || curr == 'start' && 'end' || 'middle';
8808
- updateTextAnchor(value, textNode, rec);
8809
- }
8834
+ // export function toggleTextAlign(textNode, rec) {
8835
+ // var curr = rec['text-anchor'] || 'middle';
8836
+ // var value = curr == 'middle' && 'start' || curr == 'start' && 'end' || 'middle';
8837
+ // updateTextAnchor(value, textNode, rec);
8838
+ // }
8810
8839
 
8811
8840
  // Set an attribute on a <text> node and any child <tspan> elements
8812
8841
  // (mapshaper's svg labels require tspans to have the same x and dx values
@@ -8838,6 +8867,7 @@
8838
8867
  var rect = textNode.getBoundingClientRect();
8839
8868
  var labelCenterX = rect.left - svg.getBoundingClientRect().left + rect.width / 2;
8840
8869
  var xpct = (labelCenterX - p[0]) / rect.width; // offset of label center from anchor center
8870
+
8841
8871
  var value = xpct < -0.25 && 'end' || xpct > 0.25 && 'start' || 'middle';
8842
8872
  updateTextAnchor(value, textNode, rec);
8843
8873
  }
@@ -8849,7 +8879,6 @@
8849
8879
  var curr = rec['text-anchor'] || 'middle';
8850
8880
  var xshift = 0;
8851
8881
 
8852
- // console.log("anchor() curr:", curr, "xpct:", xpct, "left:", rect.left, "anchorX:", anchorX, "targ:", targ, "dx:", xshift)
8853
8882
  if (curr == 'middle' && value == 'end' || curr == 'start' && value == 'middle') {
8854
8883
  xshift = width / 2;
8855
8884
  } else if (curr == 'middle' && value == 'start' || curr == 'end' && value == 'middle') {
@@ -8861,16 +8890,29 @@
8861
8890
  }
8862
8891
  if (xshift) {
8863
8892
  rec['text-anchor'] = value;
8864
- applyDelta(rec, 'dx', Math.round(xshift));
8893
+ applyDelta(rec, 'dx', xshift / getScaleAttribute(textNode));
8865
8894
  }
8866
8895
  }
8867
8896
 
8868
- // handle either numeric strings or numbers in fields
8897
+ function getScaleAttribute(node) {
8898
+ // this is fragile, consider passing in the value of <MapExtent>.getSymbolScale()
8899
+ var transform = node.getAttribute('transform') ||
8900
+ node.parentNode.getAttribute('transform'); // compound label puts it here
8901
+ var match = /scale\(([^)]+)\)/.exec(transform || '');
8902
+ return match ? parseFloat(match[1]) : 1;
8903
+ }
8904
+
8905
+ // handle either numeric strings or numbers in record
8869
8906
  function applyDelta(rec, key, delta) {
8870
8907
  var currVal = rec[key];
8871
- var isString = utils$1.isString(currVal);
8872
8908
  var newVal = (+currVal + delta) || 0;
8873
- rec[key] = isString ? String(newVal) : newVal;
8909
+ updateNumber(rec, key, newVal);
8910
+ }
8911
+
8912
+ // handle either numeric strings or numbers in record
8913
+ function updateNumber(rec, key, num) {
8914
+ var isString = utils$1.isString(rec[key]);
8915
+ rec[key] = isString ? String(num) : num;
8874
8916
  }
8875
8917
 
8876
8918
  function initLabelDragging(gui, ext, hit) {
@@ -8884,9 +8926,9 @@
8884
8926
 
8885
8927
  hit.on('dragstart', function(e) {
8886
8928
  if (!active(e)) return;
8887
- var textNode = getTextTarget3(e);
8929
+ var symNode = getSymbolTarget(e);
8888
8930
  var table = hit.getTargetDataTable();
8889
- if (!textNode || !table) {
8931
+ if (!symNode || !table) {
8890
8932
  activeId = -1;
8891
8933
  return false;
8892
8934
  }
@@ -8902,18 +8944,22 @@
8902
8944
  error$1("Mismatched hit ids:", e.id, activeId);
8903
8945
  }
8904
8946
  var scale = ext.getSymbolScale() || 1;
8905
- var textNode;
8947
+ var symNode, textNode;
8906
8948
  applyDelta(activeRecord, 'dx', e.dx / scale);
8907
8949
  applyDelta(activeRecord, 'dy', e.dy / scale);
8908
- textNode = getTextTarget3(e);
8909
- if (!isMultilineLabel(textNode)) {
8910
- // update anchor position of single-line labels based on label position
8911
- // relative to anchor point, for better placement when eventual display font is
8912
- // different from mapshaper's font.
8913
- autoUpdateTextAnchor(textNode, activeRecord, getDisplayCoordsById(activeId, hit.getHitTarget().layer, ext));
8914
- }
8915
- // updateSymbol(targetTextNode, activeRecord);
8916
- updateSymbol2(textNode, activeRecord, activeId);
8950
+ symNode = getSymbolTarget(e);
8951
+ textNode = getTextNode(symNode);
8952
+ // update anchor position of labels based on label position relative
8953
+ // to anchor point, for better placement when eventual display font is
8954
+ // different from mapshaper's font.
8955
+ // if (!isMultilineLabel(textNode)) {
8956
+ autoUpdateTextAnchor(textNode, activeRecord, getDisplayCoordsById(activeId, hit.getHitTarget().layer, ext));
8957
+ // }
8958
+ updateNumber(activeRecord, 'dx', internal.roundToDigits(+activeRecord.dx, 3));
8959
+ updateNumber(activeRecord, 'dy', internal.roundToDigits(+activeRecord.dy, 3));
8960
+ updateTextNode(textNode, activeRecord);
8961
+ // updateSymbolNode(symNode, activeRecord, activeId);
8962
+ gui.dispatchEvent('popup-needs-refresh');
8917
8963
  });
8918
8964
 
8919
8965
  hit.on('dragend', function(e) {
@@ -8937,32 +8983,37 @@
8937
8983
  return coords[0];
8938
8984
  }
8939
8985
 
8940
- function getTextTarget3(e) {
8986
+ function getSymbolTarget(e) {
8941
8987
  if (e.id > -1 === false || !e.container) return null;
8942
8988
  return getSymbolNodeById(e.id, e.container);
8943
8989
  }
8944
8990
 
8991
+ function getTextNode(symNode) {
8992
+ if (symNode.tagName == 'text') return symNode;
8993
+ return symNode.querySelector('text');
8994
+ }
8995
+
8945
8996
  function getSymbolNodeById(id, parent) {
8946
8997
  // TODO: optimize selector
8947
8998
  var sel = '[data-id="' + id + '"]';
8948
8999
  return parent.querySelector(sel);
8949
9000
  }
8950
9001
 
8951
- function getTextTarget2(e) {
8952
- var el = e && e.targetSymbol || null;
8953
- if (el && el.tagName == 'tspan') {
8954
- el = el.parentNode;
8955
- }
8956
- return el && el.tagName == 'text' ? el : null;
8957
- }
9002
+ // function getTextTarget2(e) {
9003
+ // var el = e && e.targetSymbol || null;
9004
+ // if (el && el.tagName == 'tspan') {
9005
+ // el = el.parentNode;
9006
+ // }
9007
+ // return el && el.tagName == 'text' ? el : null;
9008
+ // }
8958
9009
 
8959
- function getTextTarget(e) {
8960
- var el = e.target;
8961
- if (el.tagName == 'tspan') {
8962
- el = el.parentNode;
8963
- }
8964
- return el.tagName == 'text' ? el : null;
8965
- }
9010
+ // function getTextTarget(e) {
9011
+ // var el = e.target;
9012
+ // if (el.tagName == 'tspan') {
9013
+ // el = el.parentNode;
9014
+ // }
9015
+ // return el.tagName == 'text' ? el : null;
9016
+ // }
8966
9017
 
8967
9018
  function getLabelRecordById(id) {
8968
9019
  var table = hit.getTargetDataTable();
@@ -8981,7 +9032,7 @@
8981
9032
  }
8982
9033
 
8983
9034
  // update symbol by setting attributes
8984
- function updateSymbol(node, d) {
9035
+ function updateTextNode(node, d) {
8985
9036
  var a = d['text-anchor'];
8986
9037
  if (a) node.setAttribute('text-anchor', a);
8987
9038
  setMultilineAttribute(node, 'dx', d.dx || 0);
@@ -8989,7 +9040,8 @@
8989
9040
  }
8990
9041
 
8991
9042
  // update symbol by re-rendering it
8992
- function updateSymbol2(node, d, id) {
9043
+ // fails when symbol includes a dot (<g><circle/><text/></g> structure)
9044
+ function updateSymbolNode(node, d, id) {
8993
9045
  var o = internal.svg.renderStyledLabel(d); // TODO: symbol support
8994
9046
  var activeLayer = hit.getHitTarget().layer;
8995
9047
  var xy = activeLayer.shapes[id][0];
@@ -9002,8 +9054,6 @@
9002
9054
  g.innerHTML = internal.svg.stringify(o);
9003
9055
  node2 = g.firstChild;
9004
9056
  node.parentNode.replaceChild(node2, node);
9005
- gui.dispatchEvent('popup-needs-refresh');
9006
- return node2;
9007
9057
  }
9008
9058
  }
9009
9059
 
@@ -9347,50 +9397,22 @@
9347
9397
  dotColor: violet,
9348
9398
  dotSize: 3
9349
9399
  }, polyline: {
9350
- strokeColor: black, // violet,
9400
+ strokeColor: violet, // black, // violet,
9351
9401
  strokeWidth: 3
9352
9402
  }
9353
9403
  };
9354
9404
 
9355
- function getIntersectionStyle(lyr) {
9405
+ function getIntersectionStyle(lyr, opts) {
9356
9406
  return getDefaultStyle(lyr, intersectionStyle);
9357
9407
  }
9358
9408
 
9359
- function getDefaultStyle(lyr, baseStyle) {
9360
- var style = utils$1.extend({}, baseStyle);
9361
- // reduce the dot size of large point layers
9362
- if (lyr.geometry_type == 'point' && style.dotSize > 0) {
9363
- style.dotSize *= getDotScale$1(lyr);
9364
- }
9365
- return style;
9366
- }
9367
-
9368
- function getDotScale$1(lyr) {
9369
- var topTier = 50000;
9370
- var n = countPoints(lyr.shapes, topTier + 2); // short-circuit point counting above top threshold
9371
- var k = n < 200 && 4 || n < 2500 && 3 || n < 10000 && 2 || 1;
9372
- // var k = n >= topTier && 0.25 || n > 10000 && 0.45 || n > 2500 && 0.65 || n > 200 && 0.85 || 1;
9373
- return k;
9374
- }
9375
-
9376
- function countPoints(shapes, max) {
9377
- var count = 0;
9378
- var i, n, shp;
9379
- max = max || Infinity;
9380
- for (i=0, n=shapes.length; i<n && count<=max; i++) {
9381
- shp = shapes[i];
9382
- count += shp ? shp.length : 0;
9383
- }
9384
- return count;
9385
- }
9386
-
9387
9409
  // Style for unselected layers with visibility turned on
9388
9410
  // (styled layers have)
9389
- function getReferenceStyle(lyr) {
9411
+ function getReferenceLayerStyle(lyr, opts) {
9390
9412
  var style;
9391
- if (layerHasCanvasDisplayStyle(lyr)) {
9413
+ if (layerHasCanvasDisplayStyle(lyr) && !opts.outlineMode) {
9392
9414
  style = getCanvasDisplayStyle(lyr);
9393
- } else if (internal.layerHasLabels(lyr)) {
9415
+ } else if (internal.layerHasLabels(lyr) && !opts.outlineMode) {
9394
9416
  style = {dotSize: 0}; // no reference dots if labels are visible
9395
9417
  } else {
9396
9418
  style = getDefaultStyle(lyr, referenceStyle);
@@ -9398,13 +9420,13 @@
9398
9420
  return style;
9399
9421
  }
9400
9422
 
9401
- function getActiveStyle(lyr, darkMode) {
9423
+ function getActiveLayerStyle(lyr, opts) {
9402
9424
  var style;
9403
- if (layerHasCanvasDisplayStyle(lyr)) {
9425
+ if (layerHasCanvasDisplayStyle(lyr) && !opts.outlineMode) {
9404
9426
  style = getCanvasDisplayStyle(lyr);
9405
- } else if (internal.layerHasLabels(lyr)) {
9427
+ } else if (internal.layerHasLabels(lyr) && !opts.outlineMode) {
9406
9428
  style = getDefaultStyle(lyr, activeStyleForLabels);
9407
- } else if (darkMode) {
9429
+ } else if (opts.darkMode) {
9408
9430
  style = getDefaultStyle(lyr, activeStyleDarkMode);
9409
9431
  } else {
9410
9432
  style = getDefaultStyle(lyr, activeStyle);
@@ -9412,21 +9434,6 @@
9412
9434
  return style;
9413
9435
  }
9414
9436
 
9415
- // style for vertex edit mode
9416
- function getVertexStyle(lyr, o) {
9417
- return {
9418
- ids: o.ids,
9419
- overlay: true,
9420
- strokeColor: black,
9421
- strokeWidth: 1.5,
9422
- vertices: true,
9423
- vertex_overlay_color: violet,
9424
- vertex_overlay: o.hit_coordinates || null,
9425
- selected_points: o.selected_points || null,
9426
- fillColor: null
9427
- };
9428
- }
9429
-
9430
9437
  // Returns a display style for the overlay layer.
9431
9438
  // The overlay layer renders several kinds of feature, each of which is displayed
9432
9439
  // with a different style.
@@ -9435,47 +9442,104 @@
9435
9442
  // * selected shapes
9436
9443
  // * pinned shapes
9437
9444
  //
9438
- function getOverlayStyle(lyr, o) {
9439
- if (o.mode == 'vertices') {
9440
- return getVertexStyle(lyr, o);
9445
+ function getOverlayStyle(baseLyr, o, opts) {
9446
+ if (opts.interactionMode == 'vertices') {
9447
+ return getVertexStyle(baseLyr, o);
9441
9448
  }
9442
- var geomType = lyr.geometry_type;
9449
+ var geomType = baseLyr.geometry_type;
9443
9450
  var topId = o.id; // pinned id (if pinned) or hover id
9444
9451
  var topIdx = -1;
9445
9452
  var styler = function(style, i) {
9446
- utils$1.extend(style, i === topIdx ? topStyle: baseStyle);
9453
+ var defaultStyle = i === topIdx ? topStyle : outlineStyle;
9454
+ if (baseStyle.styler) {
9455
+ // TODO: render default stroke widths without scaling
9456
+ // (will need to pass symbol scale to the styler function)
9457
+ style.strokeWidth = defaultStyle.strokeWidth;
9458
+ baseStyle.styler(style, i); // get styled stroke width (if set)
9459
+ style.strokeColor = defaultStyle.strokeColor;
9460
+ style.fillColor = defaultStyle.fillColor;
9461
+ } else {
9462
+ Object.assign(style, defaultStyle);
9463
+ }
9447
9464
  };
9448
- var baseStyle = getDefaultStyle(lyr, selectionStyles[geomType]);
9465
+ var baseStyle = getActiveLayerStyle(baseLyr, opts);
9466
+ var outlineStyle = getDefaultStyle(baseLyr, selectionStyles[geomType]);
9449
9467
  var topStyle;
9450
9468
  var ids = o.ids.filter(function(i) {
9451
9469
  return i != o.id; // move selected id to the end
9452
9470
  });
9453
9471
  if (o.id > -1) { // pinned or hover style
9454
- topStyle = getSelectedFeatureStyle(lyr, o);
9472
+ topStyle = getSelectedFeatureStyle(baseLyr, o, opts);
9455
9473
  topIdx = ids.length;
9456
9474
  ids.push(o.id); // put the pinned/hover feature last in the render order
9457
9475
  }
9458
9476
  var style = {
9459
- styler: styler,
9460
- ids: ids,
9477
+ baseStyle: baseStyle,
9478
+ styler,
9479
+ ids,
9461
9480
  overlay: true
9462
9481
  };
9463
9482
 
9464
- if (layerHasCanvasDisplayStyle(lyr)) {
9483
+ if (layerHasCanvasDisplayStyle(baseLyr) && !opts.outlineMode) {
9465
9484
  if (geomType == 'point') {
9466
- style.styler = getOverlayPointStyler(getCanvasDisplayStyle(lyr).styler, styler);
9485
+ style.styler = getOverlayPointStyler(getCanvasDisplayStyle(baseLyr).styler, styler);
9467
9486
  }
9468
9487
  style.type = 'styled';
9469
9488
  }
9470
9489
  return ids.length > 0 ? style : null;
9471
9490
  }
9472
9491
 
9473
- function getSelectedFeatureStyle(lyr, o) {
9492
+
9493
+ function getDefaultStyle(lyr, baseStyle) {
9494
+ var style = Object.assign({}, baseStyle);
9495
+ // reduce the dot size of large point layers
9496
+ if (lyr.geometry_type == 'point' && style.dotSize > 0) {
9497
+ style.dotSize *= getDotScale$1(lyr);
9498
+ }
9499
+ return style;
9500
+ }
9501
+
9502
+ function getDotScale$1(lyr) {
9503
+ var topTier = 10000;
9504
+ var n = countPoints(lyr.shapes, topTier); // short-circuit point counting above top threshold
9505
+ var k = n < 200 && 4 || n < 2500 && 3 || n < topTier && 2 || 1;
9506
+ return k;
9507
+ }
9508
+
9509
+ function countPoints(shapes, max) {
9510
+ var count = 0;
9511
+ var i, n, shp;
9512
+ max = max || Infinity;
9513
+ for (i=0, n=shapes.length; i<n && count<max; i++) {
9514
+ shp = shapes[i];
9515
+ count += shp ? shp.length : 0;
9516
+ }
9517
+ return count;
9518
+ }
9519
+
9520
+
9521
+ // style for vertex edit mode
9522
+ function getVertexStyle(lyr, o) {
9523
+ return {
9524
+ ids: o.ids,
9525
+ overlay: true,
9526
+ strokeColor: black,
9527
+ strokeWidth: 1.5,
9528
+ vertices: true,
9529
+ vertex_overlay_color: violet,
9530
+ vertex_overlay: o.hit_coordinates || null,
9531
+ selected_points: o.selected_points || null,
9532
+ fillColor: null
9533
+ };
9534
+ }
9535
+
9536
+
9537
+ function getSelectedFeatureStyle(lyr, o, opts) {
9474
9538
  var isPinned = o.pinned;
9475
9539
  var inSelection = o.ids.indexOf(o.id) > -1;
9476
9540
  var geomType = lyr.geometry_type;
9477
9541
  var style;
9478
- if (isPinned && o.mode == 'rectangles') {
9542
+ if (isPinned && opts.interactionMode == 'rectangles') {
9479
9543
  // kludge for rectangle editing mode
9480
9544
  style = selectionStyles[geomType];
9481
9545
  } else if (isPinned) {
@@ -9903,19 +9967,13 @@
9903
9967
  }
9904
9968
 
9905
9969
  function calcBounds(cx, cy, scale) {
9906
- var full, bounds, w, h;
9907
- if (_frame) {
9908
- full = fillOutFrameBounds(_frame);
9909
- } else {
9910
- full = fillOut(_fullBounds);
9911
- }
9970
+ var full = fillOut(_fullBounds);
9912
9971
  if (_strictBounds) {
9913
9972
  full = fitIn(full, _strictBounds);
9914
9973
  }
9915
- w = full.width() / scale;
9916
- h = full.height() / scale;
9917
- bounds = new Bounds(cx - w/2, cy - h/2, cx + w/2, cy + h/2);
9918
- return bounds;
9974
+ var w = full.width() / scale;
9975
+ var h = full.height() / scale;
9976
+ return new Bounds(cx - w/2, cy - h/2, cx + w/2, cy + h/2);
9919
9977
  }
9920
9978
 
9921
9979
  // Calculate viewport bounds from frame data
@@ -10235,7 +10293,7 @@
10235
10293
  var iter = new internal.ShapeIter(arcs);
10236
10294
  var t = getScaledTransform(_ext);
10237
10295
  var bounds = _ext.getBounds();
10238
- var radius = (style.strokeWidth > 2 ? style.strokeWidth * 0.9 : 2) * GUI.getPixelRatio() * getScaledLineScale(_ext);
10296
+ var radius = (style.strokeWidth > 2 ? style.strokeWidth * 0.9 : 2) * GUI.getPixelRatio() * getScaledLineScale(_ext, style);
10239
10297
  var color = style.strokeColor || 'black';
10240
10298
 
10241
10299
  var i, j, p;
@@ -10269,14 +10327,16 @@
10269
10327
  _self.drawStyledPaths = function(shapes, arcs, style, filter) {
10270
10328
  var styleIndex = {};
10271
10329
  var batchSize = 1500;
10272
- var startPath = getPathStart(_ext, getScaledLineScale(_ext));
10330
+ var startPath = getPathStart(_ext, getScaledLineScale(_ext, style));
10273
10331
  var draw = getShapePencil(arcs, _ext);
10274
10332
  var key, item, shp;
10275
10333
  var styler = style.styler || null;
10276
10334
  for (var i=0; i<shapes.length; i++) {
10277
10335
  shp = shapes[i];
10278
10336
  if (!shp || filter && !filter(shp)) continue;
10279
- if (styler) styler(style, i);
10337
+ if (styler) {
10338
+ styler(style, i);
10339
+ }
10280
10340
  if (style.overlay || style.opacity < 1 || style.fillOpacity < 1 || style.strokeOpacity < 1 || style.fillEffect) {
10281
10341
  // don't batch shapes with opacity, in case they overlap
10282
10342
  drawPaths([shp], startPath, draw, style);
@@ -10445,7 +10505,7 @@
10445
10505
  return (style.strokeWidth > 0 ? style.strokeColor + '~' + style.strokeWidth +
10446
10506
  '~' + (style.lineDash ? style.lineDash + '~' : '') : '') +
10447
10507
  (style.fillColor || '') +
10448
- // styles with <1 opacity are no longer batch-rendered
10508
+ // styles with <1 opacity are no longer batch-rendered, not relevent to key
10449
10509
  // (style.strokeOpacity >= 0 ? style.strokeOpacity + '~' : '') : '') +
10450
10510
  // (style.fillOpacity ? '~' + style.fillOpacity : '') +
10451
10511
  // (style.opacity < 1 ? '~' + style.opacity : '') +
@@ -10454,9 +10514,17 @@
10454
10514
  return _self;
10455
10515
  }
10456
10516
 
10457
- function getScaledLineScale(ext) {
10517
+ function getScaledLineScale(ext, style) {
10458
10518
  var previewScale = ext.getSymbolScale();
10459
- return previewScale == 1 ? getLineScale(ext) : previewScale;
10519
+ var k = 1;
10520
+ if (previewScale == 1 || style.type != 'styled' || style.baseStyle && style.baseStyle.type != 'styled') {
10521
+ return getLineScale(ext);
10522
+ }
10523
+ if (style.baseStyle?.type == 'styled') {
10524
+ // bump up overlay line width in preview mode
10525
+ k = previewScale < 2 && 2 || previewScale < 5 && 1.5 || previewScale < 10 && 1.25 || 1.1;
10526
+ }
10527
+ return previewScale * k;
10460
10528
  }
10461
10529
 
10462
10530
  // Vary line width according to zoom ratio.
@@ -10626,9 +10694,6 @@
10626
10694
  return function(ctx, style) {
10627
10695
  var strokeWidth;
10628
10696
  ctx.beginPath();
10629
- // if (style.opacity >= 0) {
10630
- // ctx.globalAlpha = style.opacity;
10631
- // }
10632
10697
  if (style.strokeWidth > 0) {
10633
10698
  strokeWidth = style.strokeWidth;
10634
10699
  if (pixRatio > 1) {
@@ -11587,7 +11652,7 @@
11587
11652
  if (lyr == _intersectionLyr) return; // no change
11588
11653
  if (lyr) {
11589
11654
  _intersectionLyr = getDisplayLayer(lyr, dataset, getDisplayOptions());
11590
- _intersectionLyr.style = getIntersectionStyle(_intersectionLyr.layer);
11655
+ _intersectionLyr.style = getIntersectionStyle(_intersectionLyr.layer, getGlobalStyleOptions());
11591
11656
  } else {
11592
11657
  _intersectionLyr = null;
11593
11658
  }
@@ -11623,6 +11688,7 @@
11623
11688
  };
11624
11689
 
11625
11690
  this.getExtent = function() {return _ext;};
11691
+ this.getMouse = function() {return _mouse;};
11626
11692
  this.isActiveLayer = isActiveLayer;
11627
11693
  this.isVisibleLayer = isVisibleLayer;
11628
11694
  this.getActiveLayer = function() { return _activeLyr; };
@@ -11659,6 +11725,15 @@
11659
11725
  updateFullBounds();
11660
11726
  };
11661
11727
 
11728
+ function getGlobalStyleOptions() {
11729
+ var mode = gui.state.interaction_mode;
11730
+ return {
11731
+ darkMode: !!gui.state.dark_basemap,
11732
+ outlineMode: mode == 'vertices',
11733
+ interactionMode: mode
11734
+ };
11735
+ }
11736
+
11662
11737
  // Refresh map display in response to data changes, layer selection, etc.
11663
11738
  function onUpdate(e) {
11664
11739
  var prevLyr = _activeLyr || null;
@@ -11691,7 +11766,7 @@
11691
11766
  }
11692
11767
 
11693
11768
  _activeLyr = getDisplayLayer(e.layer, e.dataset, getDisplayOptions());
11694
- _activeLyr.style = getActiveStyle(_activeLyr.layer, gui.state.dark_basemap);
11769
+ _activeLyr.style = getActiveLayerStyle(_activeLyr.layer, getGlobalStyleOptions());
11695
11770
  _activeLyr.active = true;
11696
11771
 
11697
11772
  if (popupCanStayOpen(e.flags)) {
@@ -11749,7 +11824,7 @@
11749
11824
  }
11750
11825
 
11751
11826
  function updateOverlayLayer(e) {
11752
- var style = getOverlayStyle(_activeLyr.layer, e);
11827
+ var style = getOverlayStyle(_activeLyr.layer, e, getGlobalStyleOptions());
11753
11828
  if (style) {
11754
11829
  _overlayLyr = utils$1.defaults({
11755
11830
  layer: filterLayerByIds(_activeLyr.layer, style.ids),
@@ -11795,7 +11870,12 @@
11795
11870
  }
11796
11871
 
11797
11872
  function calcFullBounds() {
11798
- var b = getContentLayerBounds();
11873
+ var b;
11874
+ if (isPreviewView()) {
11875
+ b = new Bounds(getFrameData().bbox);
11876
+ } else {
11877
+ b = getContentLayerBounds();
11878
+ }
11799
11879
 
11800
11880
  // add margin
11801
11881
  // use larger margin for small sizes
@@ -11822,7 +11902,7 @@
11822
11902
  }
11823
11903
 
11824
11904
  function isTableView() {
11825
- return !isPreviewView() && !!_activeLyr.tabular;
11905
+ return !!_activeLyr.tabular;
11826
11906
  }
11827
11907
 
11828
11908
  function findFrameLayer() {
@@ -11833,8 +11913,7 @@
11833
11913
 
11834
11914
  // Preview view: symbols are scaled based on display size of frame layer
11835
11915
  function isPreviewView() {
11836
- var data = getFrameData();
11837
- return !!data;
11916
+ return !isTableView() && !!getFrameData();
11838
11917
  }
11839
11918
 
11840
11919
  function getFrameData() {
@@ -11873,7 +11952,9 @@
11873
11952
 
11874
11953
  function getContentLayers() {
11875
11954
  var layers = getVisibleMapLayers();
11876
- if (isTableView()) return findActiveLayer(layers);
11955
+ if (isTableView()) {
11956
+ return findActiveLayer(layers);
11957
+ }
11877
11958
  return layers.filter(function(o) {
11878
11959
  return !!o.geographic;
11879
11960
  });
@@ -11896,9 +11977,10 @@
11896
11977
  function updateLayerStyles(layers) {
11897
11978
  layers.forEach(function(mapLayer, i) {
11898
11979
  if (mapLayer.active) {
11899
- // assume: style is already assigned
11980
+ // regenerating active style everytime, to support style change when
11981
+ // switching between outline and preview modes.
11982
+ mapLayer.style = getActiveLayerStyle(mapLayer.layer, getGlobalStyleOptions());
11900
11983
  if (mapLayer.style.type != 'styled' && layers.length > 1 && mapLayer.style.strokeColors) {
11901
- // if (false) { // always show ghosted arcs
11902
11984
  // kludge to hide ghosted layers when reference layers are present
11903
11985
  // TODO: consider never showing ghosted layers (which appear after
11904
11986
  // commands like dissolve and filter).
@@ -11910,7 +11992,7 @@
11910
11992
  if (mapLayer.layer == _activeLyr.layer) {
11911
11993
  console.error("Error: shared map layer");
11912
11994
  }
11913
- mapLayer.style = getReferenceStyle(mapLayer.layer);
11995
+ mapLayer.style = getReferenceLayerStyle(mapLayer.layer, getGlobalStyleOptions());
11914
11996
  }
11915
11997
  });
11916
11998
  }