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.
- package/mapshaper.js +341 -150
- package/package.json +2 -2
- package/www/mapshaper-gui.js +243 -161
- package/www/mapshaper.js +341 -150
package/www/mapshaper-gui.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
7976
|
-
|
|
7977
|
-
|
|
7978
|
-
|
|
7979
|
-
|
|
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
|
-
|
|
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
|
-
|
|
8807
|
-
|
|
8808
|
-
|
|
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',
|
|
8893
|
+
applyDelta(rec, 'dx', xshift / getScaleAttribute(textNode));
|
|
8865
8894
|
}
|
|
8866
8895
|
}
|
|
8867
8896
|
|
|
8868
|
-
|
|
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
|
|
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
|
|
8929
|
+
var symNode = getSymbolTarget(e);
|
|
8888
8930
|
var table = hit.getTargetDataTable();
|
|
8889
|
-
if (!
|
|
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
|
-
|
|
8909
|
-
|
|
8910
|
-
|
|
8911
|
-
|
|
8912
|
-
|
|
8913
|
-
|
|
8914
|
-
|
|
8915
|
-
//
|
|
8916
|
-
|
|
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
|
|
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
|
-
|
|
8953
|
-
|
|
8954
|
-
|
|
8955
|
-
|
|
8956
|
-
|
|
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
|
-
|
|
8961
|
-
|
|
8962
|
-
|
|
8963
|
-
|
|
8964
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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(
|
|
9439
|
-
if (
|
|
9440
|
-
return getVertexStyle(
|
|
9445
|
+
function getOverlayStyle(baseLyr, o, opts) {
|
|
9446
|
+
if (opts.interactionMode == 'vertices') {
|
|
9447
|
+
return getVertexStyle(baseLyr, o);
|
|
9441
9448
|
}
|
|
9442
|
-
var geomType =
|
|
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
|
-
|
|
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 =
|
|
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(
|
|
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
|
-
|
|
9460
|
-
|
|
9477
|
+
baseStyle: baseStyle,
|
|
9478
|
+
styler,
|
|
9479
|
+
ids,
|
|
9461
9480
|
overlay: true
|
|
9462
9481
|
};
|
|
9463
9482
|
|
|
9464
|
-
if (layerHasCanvasDisplayStyle(
|
|
9483
|
+
if (layerHasCanvasDisplayStyle(baseLyr) && !opts.outlineMode) {
|
|
9465
9484
|
if (geomType == 'point') {
|
|
9466
|
-
style.styler = getOverlayPointStyler(getCanvasDisplayStyle(
|
|
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
|
-
|
|
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 &&
|
|
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
|
|
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
|
-
|
|
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)
|
|
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
|
-
|
|
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 =
|
|
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
|
|
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
|
|
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
|
-
|
|
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())
|
|
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
|
-
//
|
|
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 =
|
|
11995
|
+
mapLayer.style = getReferenceLayerStyle(mapLayer.layer, getGlobalStyleOptions());
|
|
11914
11996
|
}
|
|
11915
11997
|
});
|
|
11916
11998
|
}
|