mapshaper 0.5.84 → 0.5.88
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 +420 -128
- package/package.json +1 -1
- package/www/mapshaper-gui.js +274 -140
- package/www/mapshaper.js +420 -128
- package/www/nacis/Makefile +22 -0
- package/www/nacis/Makefile.txt +22 -0
- package/www/nacis/images/close.png +0 -0
- package/www/nacis/images/eye.png +0 -0
- package/www/nacis/images/eye2.png +0 -0
- package/www/nacis/index.html +262 -0
- package/www/nacis/manifest.js +27 -0
- package/www/nacis/map.svg +12308 -0
- package/CHANGELOG.md +0 -1285
package/package.json
CHANGED
package/www/mapshaper-gui.js
CHANGED
|
@@ -182,6 +182,10 @@
|
|
|
182
182
|
return (el && (el.tagName == 'INPUT' || el.contentEditable == 'true')) ? el : null;
|
|
183
183
|
};
|
|
184
184
|
|
|
185
|
+
GUI.textIsSelected = function() {
|
|
186
|
+
return !!GUI.getInputElement();
|
|
187
|
+
};
|
|
188
|
+
|
|
185
189
|
GUI.selectElement = function(el) {
|
|
186
190
|
var range = document.createRange(),
|
|
187
191
|
sel = window.getSelection();
|
|
@@ -1027,6 +1031,10 @@
|
|
|
1027
1031
|
var types = Array.from(e.clipboardData.types || []).join(',');
|
|
1028
1032
|
var items = Array.from(e.clipboardData.items || []);
|
|
1029
1033
|
var files;
|
|
1034
|
+
if (GUI.textIsSelected()) {
|
|
1035
|
+
// user is probably pasting text into an editable text field
|
|
1036
|
+
return;
|
|
1037
|
+
}
|
|
1030
1038
|
block(e);
|
|
1031
1039
|
// Browser compatibility (tested on MacOS only):
|
|
1032
1040
|
// Chrome and Safari: full support
|
|
@@ -3395,7 +3403,7 @@
|
|
|
3395
3403
|
GUI.onClick(entry, function() {
|
|
3396
3404
|
var target = findLayerById(id);
|
|
3397
3405
|
// don't select if user is typing or dragging
|
|
3398
|
-
if (!GUI.
|
|
3406
|
+
if (!GUI.textIsSelected() && !dragging) {
|
|
3399
3407
|
gui.clearMode();
|
|
3400
3408
|
if (!map.isActiveLayer(target.layer)) {
|
|
3401
3409
|
model.selectLayer(target.layer, target.dataset);
|
|
@@ -3574,6 +3582,153 @@
|
|
|
3574
3582
|
}
|
|
3575
3583
|
}
|
|
3576
3584
|
|
|
3585
|
+
// import { cloneShape } from '../paths/mapshaper-shape-utils';
|
|
3586
|
+
// import { copyRecord } from '../datatable/mapshaper-data-utils';
|
|
3587
|
+
var snapVerticesToPoint$1 = internal.snapVerticesToPoint;
|
|
3588
|
+
var cloneShape = internal.cloneShape;
|
|
3589
|
+
var copyRecord = internal.copyRecord;
|
|
3590
|
+
|
|
3591
|
+
function Undo(gui) {
|
|
3592
|
+
var history, offset, stashedUndo;
|
|
3593
|
+
reset();
|
|
3594
|
+
|
|
3595
|
+
function reset() {
|
|
3596
|
+
history = [];
|
|
3597
|
+
stashedUndo = null;
|
|
3598
|
+
offset = 0;
|
|
3599
|
+
}
|
|
3600
|
+
|
|
3601
|
+
|
|
3602
|
+
function isUndoEvt(e) {
|
|
3603
|
+
return (e.ctrlKey || e.metaKey) && !e.shiftKey && e.key == 'z';
|
|
3604
|
+
}
|
|
3605
|
+
|
|
3606
|
+
function isRedoEvt(e) {
|
|
3607
|
+
return (e.ctrlKey || e.metaKey) && (e.shiftKey && e.key == 'z' || !e.shiftKey && e.key == 'y');
|
|
3608
|
+
}
|
|
3609
|
+
|
|
3610
|
+
gui.keyboard.on('keydown', function(evt) {
|
|
3611
|
+
var e = evt.originalEvent,
|
|
3612
|
+
kc = e.keyCode;
|
|
3613
|
+
if (isUndoEvt(e)) {
|
|
3614
|
+
this.undo();
|
|
3615
|
+
e.stopPropagation();
|
|
3616
|
+
e.preventDefault();
|
|
3617
|
+
}
|
|
3618
|
+
if (isRedoEvt(e)) {
|
|
3619
|
+
this.redo();
|
|
3620
|
+
e.stopPropagation();
|
|
3621
|
+
e.preventDefault();
|
|
3622
|
+
}
|
|
3623
|
+
|
|
3624
|
+
}, this, 10);
|
|
3625
|
+
|
|
3626
|
+
// undo/redo point/symbol dragging
|
|
3627
|
+
//
|
|
3628
|
+
gui.on('symbol_dragstart', function(e) {
|
|
3629
|
+
stashedUndo = this.makePointSetter(e.FID);
|
|
3630
|
+
}, this);
|
|
3631
|
+
|
|
3632
|
+
gui.on('symbol_dragend', function(e) {
|
|
3633
|
+
var redo = this.makePointSetter(e.FID);
|
|
3634
|
+
this.addHistoryState(stashedUndo, redo);
|
|
3635
|
+
}, this);
|
|
3636
|
+
|
|
3637
|
+
// undo/redo label dragging
|
|
3638
|
+
//
|
|
3639
|
+
gui.on('label_dragstart', function(e) {
|
|
3640
|
+
stashedUndo = this.makeDataSetter(e.FID);
|
|
3641
|
+
}, this);
|
|
3642
|
+
|
|
3643
|
+
gui.on('label_dragend', function(e) {
|
|
3644
|
+
var redo = this.makeDataSetter(e.FID);
|
|
3645
|
+
this.addHistoryState(stashedUndo, redo);
|
|
3646
|
+
}, this);
|
|
3647
|
+
|
|
3648
|
+
// undo/redo data editing
|
|
3649
|
+
// TODO: consider setting selected feature to the undo/redo target feature
|
|
3650
|
+
//
|
|
3651
|
+
gui.on('data_preupdate', function(e) {
|
|
3652
|
+
stashedUndo = this.makeDataSetter(e.FID);
|
|
3653
|
+
}, this);
|
|
3654
|
+
|
|
3655
|
+
gui.on('data_postupdate', function(e) {
|
|
3656
|
+
var redo = this.makeDataSetter(e.FID);
|
|
3657
|
+
this.addHistoryState(stashedUndo, redo);
|
|
3658
|
+
}, this);
|
|
3659
|
+
|
|
3660
|
+
// undo/redo vertex dragging
|
|
3661
|
+
gui.on('vertex_dragstart', function(e) {
|
|
3662
|
+
stashedUndo = this.makeVertexSetter(e.FID, e.vertex_ids);
|
|
3663
|
+
}, this);
|
|
3664
|
+
|
|
3665
|
+
gui.on('vertex_dragend', function(e) {
|
|
3666
|
+
var redo = this.makeVertexSetter(e.FID, e.vertex_ids);
|
|
3667
|
+
this.addHistoryState(stashedUndo, redo);
|
|
3668
|
+
}, this);
|
|
3669
|
+
|
|
3670
|
+
this.clear = function() {
|
|
3671
|
+
reset();
|
|
3672
|
+
};
|
|
3673
|
+
|
|
3674
|
+
this.makePointSetter = function(i) {
|
|
3675
|
+
var target = gui.model.getActiveLayer();
|
|
3676
|
+
var shp = cloneShape(target.layer.shapes[i]);
|
|
3677
|
+
return function() {
|
|
3678
|
+
target.layer.shapes[i] = shp;
|
|
3679
|
+
};
|
|
3680
|
+
};
|
|
3681
|
+
|
|
3682
|
+
this.makeDataSetter = function(id) {
|
|
3683
|
+
var target = gui.model.getActiveLayer();
|
|
3684
|
+
var rec = copyRecord(target.layer.data.getRecordAt(id));
|
|
3685
|
+
return function() {
|
|
3686
|
+
target.layer.data.getRecords()[id] = rec;
|
|
3687
|
+
gui.dispatchEvent('popup-needs-refresh');
|
|
3688
|
+
};
|
|
3689
|
+
};
|
|
3690
|
+
|
|
3691
|
+
this.makeVertexSetter = function(fid, ids) {
|
|
3692
|
+
var target = gui.model.getActiveLayer();
|
|
3693
|
+
var arcs = target.dataset.arcs;
|
|
3694
|
+
var p = internal.getVertexCoords(ids[0], arcs);
|
|
3695
|
+
return function() {
|
|
3696
|
+
snapVerticesToPoint$1(ids, p, arcs, true);
|
|
3697
|
+
};
|
|
3698
|
+
};
|
|
3699
|
+
|
|
3700
|
+
this.addHistoryState = function(undo, redo) {
|
|
3701
|
+
if (offset > 0) {
|
|
3702
|
+
history.splice(-offset);
|
|
3703
|
+
offset = 0;
|
|
3704
|
+
}
|
|
3705
|
+
history.push({undo, redo});
|
|
3706
|
+
};
|
|
3707
|
+
|
|
3708
|
+
this.undo = function() {
|
|
3709
|
+
var item = getHistoryItem();
|
|
3710
|
+
if (item) {
|
|
3711
|
+
offset++;
|
|
3712
|
+
item.undo();
|
|
3713
|
+
gui.dispatchEvent('map-needs-refresh');
|
|
3714
|
+
}
|
|
3715
|
+
};
|
|
3716
|
+
|
|
3717
|
+
this.redo = function() {
|
|
3718
|
+
if (offset <= 0) return;
|
|
3719
|
+
offset--;
|
|
3720
|
+
var item = getHistoryItem();
|
|
3721
|
+
item.redo();
|
|
3722
|
+
gui.dispatchEvent('map-needs-refresh');
|
|
3723
|
+
};
|
|
3724
|
+
|
|
3725
|
+
function getHistoryItem() {
|
|
3726
|
+
var item = history[history.length - offset - 1];
|
|
3727
|
+
return item || null;
|
|
3728
|
+
}
|
|
3729
|
+
|
|
3730
|
+
}
|
|
3731
|
+
|
|
3577
3732
|
function SidebarButtons(gui) {
|
|
3578
3733
|
var root = gui.container.findChild('.mshp-main-map');
|
|
3579
3734
|
var buttons = El('div').addClass('nav-buttons').appendTo(root).hide();
|
|
@@ -3705,6 +3860,7 @@
|
|
|
3705
3860
|
|
|
3706
3861
|
var menus = {
|
|
3707
3862
|
standard: ['info', 'selection', 'data', 'box'],
|
|
3863
|
+
polygons: ['info', 'selection', 'data', 'box', 'vertices'],
|
|
3708
3864
|
lines: ['info', 'selection', 'data', 'box', 'vertices'],
|
|
3709
3865
|
table: ['info', 'selection', 'data'],
|
|
3710
3866
|
labels: ['info', 'selection', 'data', 'box', 'labels', 'location'],
|
|
@@ -3816,6 +3972,9 @@
|
|
|
3816
3972
|
if (internal.layerHasPaths(o.layer) && o.layer.geometry_type == 'polyline') {
|
|
3817
3973
|
return menus.lines;
|
|
3818
3974
|
}
|
|
3975
|
+
if (internal.layerHasPaths(o.layer) && o.layer.geometry_type == 'polygon') {
|
|
3976
|
+
return menus.polygons;
|
|
3977
|
+
}
|
|
3819
3978
|
return menus.standard;
|
|
3820
3979
|
}
|
|
3821
3980
|
|
|
@@ -3888,7 +4047,9 @@
|
|
|
3888
4047
|
}
|
|
3889
4048
|
|
|
3890
4049
|
function onModeChange() {
|
|
3891
|
-
|
|
4050
|
+
var mode = getInteractionMode();
|
|
4051
|
+
gui.state.interaction_mode = mode;
|
|
4052
|
+
gui.dispatchEvent('interaction_mode_change', {mode: mode});
|
|
3892
4053
|
}
|
|
3893
4054
|
|
|
3894
4055
|
// Update button highlight and selected menu item highlight (if any)
|
|
@@ -4319,7 +4480,7 @@
|
|
|
4319
4480
|
}
|
|
4320
4481
|
|
|
4321
4482
|
// ignore keypress if no feature is selected or user is editing text
|
|
4322
|
-
if (pinnedId() == -1 || GUI.
|
|
4483
|
+
if (pinnedId() == -1 || GUI.textIsSelected()) return;
|
|
4323
4484
|
|
|
4324
4485
|
if (e.keyCode == 37 || e.keyCode == 39) {
|
|
4325
4486
|
// L/R arrow keys
|
|
@@ -4477,6 +4638,7 @@
|
|
|
4477
4638
|
|
|
4478
4639
|
// Hits are re-detected on 'hover' (if hit detection is active)
|
|
4479
4640
|
mouse.on('hover', function(e) {
|
|
4641
|
+
handlePointerEvent(e);
|
|
4480
4642
|
if (storedData.pinned || !hitTest || !active) return;
|
|
4481
4643
|
if (e.hover && isOverMap(e)) {
|
|
4482
4644
|
// mouse is hovering directly over map area -- update hit detection
|
|
@@ -5521,7 +5683,9 @@
|
|
|
5521
5683
|
} else {
|
|
5522
5684
|
// field content has changed
|
|
5523
5685
|
strval = strval2;
|
|
5686
|
+
gui.dispatchEvent('data_preupdate', {FID: currId}); // for undo/redo
|
|
5524
5687
|
rec[key] = val2;
|
|
5688
|
+
gui.dispatchEvent('data_postupdate', {FID: currId});
|
|
5525
5689
|
input.value(strval);
|
|
5526
5690
|
setFieldClass(el, val2, type);
|
|
5527
5691
|
self.dispatchEvent('update', {field: key, value: val2, id: currId});
|
|
@@ -5737,6 +5901,8 @@
|
|
|
5737
5901
|
rec[key] = isString ? String(newVal) : newVal;
|
|
5738
5902
|
}
|
|
5739
5903
|
|
|
5904
|
+
var snapVerticesToPoint = internal.snapVerticesToPoint;
|
|
5905
|
+
|
|
5740
5906
|
function getDisplayCoordsById(id, layer, ext) {
|
|
5741
5907
|
var coords = getPointCoordsById(id, layer);
|
|
5742
5908
|
return ext.translateCoords(coords[0], coords[1]);
|
|
@@ -5757,7 +5923,7 @@
|
|
|
5757
5923
|
}
|
|
5758
5924
|
|
|
5759
5925
|
|
|
5760
|
-
function
|
|
5926
|
+
function InteractiveEditor(gui, ext, hit) {
|
|
5761
5927
|
// var targetTextNode; // text node currently being dragged
|
|
5762
5928
|
var dragging = false;
|
|
5763
5929
|
var activeRecord;
|
|
@@ -5819,6 +5985,7 @@
|
|
|
5819
5985
|
if (e.mode != 'labels') {
|
|
5820
5986
|
stopDragging();
|
|
5821
5987
|
}
|
|
5988
|
+
gui.undo.clear(); // TODO: put this elsewhere?
|
|
5822
5989
|
});
|
|
5823
5990
|
|
|
5824
5991
|
// down event on svg
|
|
@@ -5830,12 +5997,17 @@
|
|
|
5830
5997
|
// 3: on other text -> stop dragging, select new text
|
|
5831
5998
|
|
|
5832
5999
|
hit.on('dragstart', function(e) {
|
|
5833
|
-
if (
|
|
5834
|
-
|
|
6000
|
+
if (e.id >= 0 === false) return;
|
|
6001
|
+
if (labelEditingEnabled() && onLabelDragStart(e)) {
|
|
6002
|
+
triggerGlobalEvent('label_dragstart', e);
|
|
6003
|
+
startDragging();
|
|
5835
6004
|
} else if (locationEditingEnabled()) {
|
|
5836
|
-
|
|
6005
|
+
triggerGlobalEvent('symbol_dragstart', e);
|
|
6006
|
+
startDragging();
|
|
5837
6007
|
} else if (vertexEditingEnabled()) {
|
|
5838
6008
|
onVertexDragStart(e);
|
|
6009
|
+
triggerGlobalEvent('vertex_dragstart', e);
|
|
6010
|
+
startDragging();
|
|
5839
6011
|
}
|
|
5840
6012
|
});
|
|
5841
6013
|
|
|
@@ -5851,70 +6023,77 @@
|
|
|
5851
6023
|
|
|
5852
6024
|
hit.on('dragend', function(e) {
|
|
5853
6025
|
if (locationEditingEnabled()) {
|
|
5854
|
-
|
|
6026
|
+
triggerGlobalEvent('symbol_dragend', e);
|
|
5855
6027
|
stopDragging();
|
|
5856
6028
|
} else if (labelEditingEnabled()) {
|
|
6029
|
+
triggerGlobalEvent('label_dragend', e);
|
|
5857
6030
|
stopDragging();
|
|
5858
6031
|
} else if (vertexEditingEnabled()) {
|
|
5859
|
-
|
|
6032
|
+
// kludge to get dataset to recalculate internal bounding boxes
|
|
6033
|
+
hit.getHitTarget().arcs.transformPoints(function() {});
|
|
6034
|
+
triggerGlobalEvent('vertex_dragend', e);
|
|
5860
6035
|
stopDragging();
|
|
5861
6036
|
}
|
|
5862
6037
|
});
|
|
5863
6038
|
|
|
5864
6039
|
hit.on('click', function(e) {
|
|
5865
6040
|
if (labelEditingEnabled()) {
|
|
6041
|
+
var target = hit.getHitTarget();
|
|
5866
6042
|
onLabelClick(e);
|
|
5867
6043
|
}
|
|
5868
6044
|
});
|
|
5869
6045
|
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
6046
|
+
// TODO: highlight hit vertex in path edit mode
|
|
6047
|
+
if (false) hit.on('hover', function(e) {
|
|
6048
|
+
if (vertexEditingEnabled() && !dragging) {
|
|
6049
|
+
onVertexHover(e);
|
|
5874
6050
|
}
|
|
6051
|
+
}, null, 100);
|
|
6052
|
+
|
|
6053
|
+
function onVertexHover(e) {
|
|
6054
|
+
// hovering in vertex edit mode: find vertex insertion point
|
|
6055
|
+
var target = hit.getHitTarget();
|
|
6056
|
+
var shp = target.layer.shapes[e.id];
|
|
6057
|
+
var p = ext.translatePixelCoords(e.x, e.y);
|
|
6058
|
+
var o = internal.findInsertionPoint(p, shp, target.arcs, ext.getPixelSize());
|
|
5875
6059
|
}
|
|
5876
6060
|
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
6061
|
+
|
|
6062
|
+
function getVertexEventData(e) {
|
|
6063
|
+
return {
|
|
6064
|
+
FID: activeId,
|
|
6065
|
+
vertexIds: activeVertexIds
|
|
6066
|
+
};
|
|
5881
6067
|
}
|
|
5882
6068
|
|
|
5883
6069
|
function onLocationDrag(e) {
|
|
5884
6070
|
var lyr = hit.getHitTarget().layer;
|
|
5885
|
-
var p = getPointCoordsById(e.id,
|
|
6071
|
+
var p = getPointCoordsById(e.id, lyr);
|
|
5886
6072
|
if (!p) return;
|
|
5887
6073
|
var diff = translateDeltaDisplayCoords(e.dx, e.dy, ext);
|
|
5888
6074
|
p[0] += diff[0];
|
|
5889
6075
|
p[1] += diff[1];
|
|
5890
|
-
|
|
6076
|
+
triggerRedraw();
|
|
5891
6077
|
triggerGlobalEvent('symbol_drag', e);
|
|
5892
6078
|
}
|
|
5893
6079
|
|
|
5894
|
-
function
|
|
6080
|
+
function onVertexDragStart(e) {
|
|
5895
6081
|
var target = hit.getHitTarget();
|
|
6082
|
+
var shp = target.layer.shapes[e.id];
|
|
5896
6083
|
var p = ext.translatePixelCoords(e.x, e.y);
|
|
5897
|
-
|
|
5898
|
-
|
|
5899
|
-
|
|
6084
|
+
activeVertexIds = internal.findNearestVertices(p, shp, target.arcs);
|
|
6085
|
+
activeId = e.id;
|
|
6086
|
+
}
|
|
6087
|
+
|
|
6088
|
+
function onVertexDrag(e) {
|
|
6089
|
+
var target = hit.getHitTarget();
|
|
5900
6090
|
if (!activeVertexIds) return; // ignore error condition
|
|
6091
|
+
var p = ext.translatePixelCoords(e.x, e.y);
|
|
5901
6092
|
if (gui.keyboard.shiftIsPressed()) {
|
|
5902
6093
|
internal.snapPointToArcEndpoint(p, activeVertexIds, target.arcs);
|
|
5903
6094
|
}
|
|
5904
|
-
activeVertexIds.
|
|
5905
|
-
|
|
5906
|
-
});
|
|
5907
|
-
self.dispatchEvent('location_change'); // signal map to redraw
|
|
5908
|
-
}
|
|
5909
|
-
|
|
5910
|
-
function onLocationDragEnd(e) {
|
|
5911
|
-
triggerGlobalEvent('symbol_dragend', e);
|
|
5912
|
-
}
|
|
5913
|
-
|
|
5914
|
-
function onVertexDragEnd(e) {
|
|
5915
|
-
// kludge to get dataset to recalculate internal bounding boxes
|
|
5916
|
-
hit.getHitTarget().arcs.transformPoints(function() {});
|
|
5917
|
-
activeVertexIds = null;
|
|
6095
|
+
snapVerticesToPoint(activeVertexIds, p, target.arcs);
|
|
6096
|
+
triggerRedraw();
|
|
5918
6097
|
}
|
|
5919
6098
|
|
|
5920
6099
|
function onLabelClick(e) {
|
|
@@ -5927,11 +6106,19 @@
|
|
|
5927
6106
|
}
|
|
5928
6107
|
}
|
|
5929
6108
|
|
|
6109
|
+
function triggerRedraw() {
|
|
6110
|
+
gui.dispatchEvent('map-needs-refresh');
|
|
6111
|
+
}
|
|
6112
|
+
|
|
5930
6113
|
function triggerGlobalEvent(type, e) {
|
|
5931
|
-
if (e.id >= 0)
|
|
5932
|
-
|
|
5933
|
-
|
|
5934
|
-
|
|
6114
|
+
if (e.id >= 0 === false) return;
|
|
6115
|
+
var o = {
|
|
6116
|
+
FID: e.id,
|
|
6117
|
+
layer_name: hit.getHitTarget().layer.name,
|
|
6118
|
+
vertex_ids: activeVertexIds
|
|
6119
|
+
};
|
|
6120
|
+
// fire event to signal external editor that symbol coords have changed
|
|
6121
|
+
gui.dispatchEvent(type, o);
|
|
5935
6122
|
}
|
|
5936
6123
|
|
|
5937
6124
|
function getLabelRecordById(id) {
|
|
@@ -5953,11 +6140,11 @@
|
|
|
5953
6140
|
function onLabelDragStart(e) {
|
|
5954
6141
|
var textNode = getTextTarget3(e);
|
|
5955
6142
|
var table = hit.getTargetDataTable();
|
|
5956
|
-
if (!textNode || !table) return;
|
|
6143
|
+
if (!textNode || !table) return false;
|
|
5957
6144
|
activeId = e.id;
|
|
5958
6145
|
activeRecord = getLabelRecordById(activeId);
|
|
5959
|
-
dragging = true;
|
|
5960
6146
|
downEvt = e;
|
|
6147
|
+
return true;
|
|
5961
6148
|
}
|
|
5962
6149
|
|
|
5963
6150
|
function onLabelDrag(e) {
|
|
@@ -6006,88 +6193,17 @@
|
|
|
6006
6193
|
}
|
|
6007
6194
|
return el.tagName == 'text' ? el : null;
|
|
6008
6195
|
}
|
|
6196
|
+
}
|
|
6009
6197
|
|
|
6010
|
-
|
|
6011
|
-
|
|
6012
|
-
// downEvt = e;
|
|
6013
|
-
// if (!textTarget) {
|
|
6014
|
-
// stopEditing();
|
|
6015
|
-
// } else if (!editing) {
|
|
6016
|
-
// // nop
|
|
6017
|
-
// } else if (textTarget == targetTextNode) {
|
|
6018
|
-
// startDragging();
|
|
6019
|
-
// } else {
|
|
6020
|
-
// startDragging();
|
|
6021
|
-
// editTextNode(textTarget);
|
|
6022
|
-
// }
|
|
6023
|
-
// });
|
|
6024
|
-
|
|
6025
|
-
// up event on svg
|
|
6026
|
-
// a: currently dragging text
|
|
6027
|
-
// -> stop dragging
|
|
6028
|
-
// b: clicked on a text feature
|
|
6029
|
-
// -> start editing it
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
// svg.addEventListener('mouseup', function(e) {
|
|
6033
|
-
// var textTarget = getTextTarget(e);
|
|
6034
|
-
// var isClick = isClickEvent(e, downEvt);
|
|
6035
|
-
// if (isClick && textTarget && textTarget == targetTextNode &&
|
|
6036
|
-
// activeRecord && isMultilineLabel(targetTextNode)) {
|
|
6037
|
-
// toggleTextAlign(targetTextNode, activeRecord);
|
|
6038
|
-
// updateSymbol();
|
|
6039
|
-
// }
|
|
6040
|
-
// if (dragging) {
|
|
6041
|
-
// stopDragging();
|
|
6042
|
-
// } else if (isClick && textTarget) {
|
|
6043
|
-
// editTextNode(textTarget);
|
|
6044
|
-
// }
|
|
6045
|
-
// });
|
|
6046
|
-
|
|
6047
|
-
// block dbl-click navigation when editing
|
|
6048
|
-
// mouse.on('dblclick', function(e) {
|
|
6049
|
-
// if (editing) e.stopPropagation();
|
|
6050
|
-
// }, null, eventPriority);
|
|
6051
|
-
|
|
6052
|
-
// mouse.on('dragstart', function(e) {
|
|
6053
|
-
// onLabelDrag(e);
|
|
6054
|
-
// }, null, eventPriority);
|
|
6055
|
-
|
|
6056
|
-
// mouse.on('drag', function(e) {
|
|
6057
|
-
// var scale = ext.getSymbolScale() || 1;
|
|
6058
|
-
// onLabelDrag(e);
|
|
6059
|
-
// if (!dragging || !activeRecord) return;
|
|
6060
|
-
// applyDelta(activeRecord, 'dx', e.dx / scale);
|
|
6061
|
-
// applyDelta(activeRecord, 'dy', e.dy / scale);
|
|
6062
|
-
// if (!isMultilineLabel(targetTextNode)) {
|
|
6063
|
-
// // update anchor position of single-line labels based on label position
|
|
6064
|
-
// // relative to anchor point, for better placement when eventual display font is
|
|
6065
|
-
// // different from mapshaper's font.
|
|
6066
|
-
// updateTextAnchor(targetTextNode, activeRecord);
|
|
6067
|
-
// }
|
|
6068
|
-
// // updateSymbol(targetTextNode, activeRecord);
|
|
6069
|
-
// targetTextNode = updateSymbol2(targetTextNode, activeRecord, activeId);
|
|
6070
|
-
// }, null, eventPriority);
|
|
6071
|
-
|
|
6072
|
-
// mouse.on('dragend', function(e) {
|
|
6073
|
-
// onLabelDrag(e);
|
|
6074
|
-
// stopDragging();
|
|
6075
|
-
// }, null, eventPriority);
|
|
6076
|
-
|
|
6077
|
-
|
|
6078
|
-
// function onLabelDrag(e) {
|
|
6079
|
-
// if (dragging) {
|
|
6080
|
-
// e.stopPropagation();
|
|
6081
|
-
// }
|
|
6082
|
-
// }
|
|
6198
|
+
function startDragging() {
|
|
6199
|
+
dragging = true;
|
|
6083
6200
|
}
|
|
6084
6201
|
|
|
6085
6202
|
function stopDragging() {
|
|
6086
6203
|
dragging = false;
|
|
6087
6204
|
activeId = -1;
|
|
6088
6205
|
activeRecord = null;
|
|
6089
|
-
|
|
6090
|
-
// svg.removeAttribute('class');
|
|
6206
|
+
activeVertexIds = null;
|
|
6091
6207
|
}
|
|
6092
6208
|
|
|
6093
6209
|
function isClickEvent(up, down) {
|
|
@@ -6098,16 +6214,6 @@
|
|
|
6098
6214
|
return dist <= 4 && elapsed < 300;
|
|
6099
6215
|
}
|
|
6100
6216
|
|
|
6101
|
-
|
|
6102
|
-
// function deselectText(el) {
|
|
6103
|
-
// el.removeAttribute('class');
|
|
6104
|
-
// }
|
|
6105
|
-
|
|
6106
|
-
// function selectText(el) {
|
|
6107
|
-
// el.setAttribute('class', 'selected');
|
|
6108
|
-
// }
|
|
6109
|
-
|
|
6110
|
-
|
|
6111
6217
|
}
|
|
6112
6218
|
|
|
6113
6219
|
var darkStroke = "#334",
|
|
@@ -6151,7 +6257,7 @@
|
|
|
6151
6257
|
dotSize: 2.5
|
|
6152
6258
|
}, polyline: {
|
|
6153
6259
|
strokeColor: black,
|
|
6154
|
-
strokeWidth: 2.5
|
|
6260
|
+
strokeWidth: 2.5,
|
|
6155
6261
|
}
|
|
6156
6262
|
},
|
|
6157
6263
|
unselectedHoverStyles = {
|
|
@@ -6465,6 +6571,7 @@
|
|
|
6465
6571
|
|
|
6466
6572
|
this.maxScale = maxScale;
|
|
6467
6573
|
|
|
6574
|
+
// Display scale, e.g. meters per pixel or degrees per pixel
|
|
6468
6575
|
this.getPixelSize = function() {
|
|
6469
6576
|
return 1 / this.getTransform().mx;
|
|
6470
6577
|
};
|
|
@@ -6656,7 +6763,10 @@
|
|
|
6656
6763
|
} else {
|
|
6657
6764
|
arcs = getArcsForRendering(obj, ext);
|
|
6658
6765
|
filter = getShapeFilter(arcs, ext);
|
|
6659
|
-
canv.
|
|
6766
|
+
canv.drawStyledPaths(layer.shapes, arcs, style, filter);
|
|
6767
|
+
if (style.vertices) {
|
|
6768
|
+
canv.drawVertices(layer.shapes, arcs, style, filter);
|
|
6769
|
+
}
|
|
6660
6770
|
}
|
|
6661
6771
|
}
|
|
6662
6772
|
|
|
@@ -6730,7 +6840,7 @@
|
|
|
6730
6840
|
|
|
6731
6841
|
/*
|
|
6732
6842
|
// Original function, not optimized
|
|
6733
|
-
_self.
|
|
6843
|
+
_self.drawStyledPaths = function(shapes, arcs, style) {
|
|
6734
6844
|
var startPath = getPathStart(_ext),
|
|
6735
6845
|
drawPath = getShapePencil(arcs, _ext),
|
|
6736
6846
|
styler = style.styler || null;
|
|
@@ -6743,8 +6853,28 @@
|
|
|
6743
6853
|
};
|
|
6744
6854
|
*/
|
|
6745
6855
|
|
|
6856
|
+
_self.drawVertices = function(shapes, arcs, style, filter) {
|
|
6857
|
+
var iter = new internal.ShapeIter(arcs);
|
|
6858
|
+
var t = getScaledTransform(_ext);
|
|
6859
|
+
var radius = (style.strokeWidth * 0.9 || 2.2) * GUI.getPixelRatio() * getScaledLineScale(_ext);
|
|
6860
|
+
var color = style.strokeColor || 'black';
|
|
6861
|
+
var shp;
|
|
6862
|
+
_ctx.beginPath();
|
|
6863
|
+
_ctx.fillStyle = color;
|
|
6864
|
+
for (var i=0; i<shapes.length; i++) {
|
|
6865
|
+
shp = shapes[i];
|
|
6866
|
+
if (!shp || filter && !filter(shp)) continue;
|
|
6867
|
+
iter.init(shp);
|
|
6868
|
+
while (iter.hasNext()) {
|
|
6869
|
+
drawCircle(iter.x * t.mx + t.bx, iter.y * t.my + t.by, radius, _ctx);
|
|
6870
|
+
}
|
|
6871
|
+
}
|
|
6872
|
+
_ctx.fill();
|
|
6873
|
+
_ctx.closePath();
|
|
6874
|
+
};
|
|
6875
|
+
|
|
6746
6876
|
// Optimized to draw paths in same-style batches (faster Canvas drawing)
|
|
6747
|
-
_self.
|
|
6877
|
+
_self.drawStyledPaths = function(shapes, arcs, style, filter) {
|
|
6748
6878
|
var styleIndex = {};
|
|
6749
6879
|
var batchSize = 1500;
|
|
6750
6880
|
var startPath = getPathStart(_ext, getScaledLineScale(_ext));
|
|
@@ -6872,7 +7002,7 @@
|
|
|
6872
7002
|
}
|
|
6873
7003
|
}
|
|
6874
7004
|
|
|
6875
|
-
// TODO: consider using
|
|
7005
|
+
// TODO: consider using drawStyledPaths(), which draws paths in batches
|
|
6876
7006
|
// for faster Canvas rendering. Downside: changes stacking order, which
|
|
6877
7007
|
// is bad if circles are graduated.
|
|
6878
7008
|
_self.drawPoints = function(shapes, style) {
|
|
@@ -7812,6 +7942,10 @@
|
|
|
7812
7942
|
_mouse.disable();
|
|
7813
7943
|
});
|
|
7814
7944
|
|
|
7945
|
+
gui.on('map-needs-refresh', function() {
|
|
7946
|
+
drawLayers();
|
|
7947
|
+
});
|
|
7948
|
+
|
|
7815
7949
|
model.on('update', onUpdate);
|
|
7816
7950
|
|
|
7817
7951
|
// Update display of segment intersections
|
|
@@ -7970,13 +8104,7 @@
|
|
|
7970
8104
|
});
|
|
7971
8105
|
}
|
|
7972
8106
|
|
|
7973
|
-
|
|
7974
|
-
_editor = new SymbolDragging2(gui, _ext, _hit);
|
|
7975
|
-
_editor.on('location_change', function(e) {
|
|
7976
|
-
// TODO: look into optimizing, so only changed symbol is redrawn
|
|
7977
|
-
drawLayers();
|
|
7978
|
-
});
|
|
7979
|
-
}
|
|
8107
|
+
_editor = new InteractiveEditor(gui, _ext, _hit);
|
|
7980
8108
|
|
|
7981
8109
|
_ext.on('change', function(e) {
|
|
7982
8110
|
if (e.reset) return; // don't need to redraw map here if extent has been reset
|
|
@@ -7996,6 +8124,10 @@
|
|
|
7996
8124
|
function updateOverlayLayer(e) {
|
|
7997
8125
|
var style = getOverlayStyle(_activeLyr.layer, e);
|
|
7998
8126
|
if (style) {
|
|
8127
|
+
// kludge to show vertices when editing path shapes
|
|
8128
|
+
if (gui.state.interaction_mode == 'vertices') {
|
|
8129
|
+
style.vertices = true;
|
|
8130
|
+
}
|
|
7999
8131
|
_overlayLyr = utils.defaults({
|
|
8000
8132
|
layer: filterLayerByIds(_activeLyr.layer, style.ids),
|
|
8001
8133
|
style: style
|
|
@@ -8235,6 +8367,8 @@
|
|
|
8235
8367
|
gui.map = new MshpMap(gui);
|
|
8236
8368
|
gui.interaction = new InteractionMode(gui);
|
|
8237
8369
|
gui.session = new SessionHistory(gui);
|
|
8370
|
+
gui.undo = new Undo(gui);
|
|
8371
|
+
gui.state = {};
|
|
8238
8372
|
|
|
8239
8373
|
gui.showProgressMessage = function(msg) {
|
|
8240
8374
|
if (!gui.progressMessage) {
|