mapshaper 0.6.82 → 0.6.83
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 +9 -8
- package/package.json +1 -1
- package/www/index.html +3 -3
- package/www/mapshaper-gui.js +458 -414
- package/www/mapshaper.js +9 -8
- package/www/page.css +46 -9
package/mapshaper.js
CHANGED
|
@@ -38860,14 +38860,15 @@ ${svg}
|
|
|
38860
38860
|
return mergeDatasetsIntoDataset(target.dataset, datasets);
|
|
38861
38861
|
};
|
|
38862
38862
|
|
|
38863
|
-
cmd.rectangle = function(
|
|
38863
|
+
cmd.rectangle = function(target, opts) {
|
|
38864
38864
|
var bounds, crsInfo;
|
|
38865
|
-
if (
|
|
38866
|
-
bounds = getLayerBounds(source.layer, source.dataset.arcs);
|
|
38867
|
-
crsInfo = getDatasetCrsInfo(source.dataset);
|
|
38868
|
-
} else if (opts.bbox) {
|
|
38865
|
+
if (opts.bbox) {
|
|
38869
38866
|
bounds = new Bounds(opts.bbox);
|
|
38870
|
-
crsInfo =
|
|
38867
|
+
crsInfo = target && getDatasetCrsInfo(target.dataset) ||
|
|
38868
|
+
probablyDecimalDegreeBounds(bounds) && getCrsInfo('wgs84') || {};
|
|
38869
|
+
} else if (target) {
|
|
38870
|
+
bounds = getLayerBounds(target.layer, target.dataset.arcs);
|
|
38871
|
+
crsInfo = getDatasetCrsInfo(target.dataset);
|
|
38871
38872
|
}
|
|
38872
38873
|
bounds = bounds && applyRectangleOptions(bounds, crsInfo.crs, opts);
|
|
38873
38874
|
if (!bounds || !bounds.hasBounds()) {
|
|
@@ -45371,7 +45372,7 @@ ${svg}
|
|
|
45371
45372
|
stop('Command requires a width= argument');
|
|
45372
45373
|
}
|
|
45373
45374
|
if (source || opts.bbox || targets.length === 0) {
|
|
45374
|
-
job.catalog.addDataset(cmd.rectangle(source, opts));
|
|
45375
|
+
job.catalog.addDataset(cmd.rectangle(source || targets?.[0], opts));
|
|
45375
45376
|
} else {
|
|
45376
45377
|
outputLayers = cmd.rectangle2(targets[0], opts);
|
|
45377
45378
|
}
|
|
@@ -45535,7 +45536,7 @@ ${svg}
|
|
|
45535
45536
|
});
|
|
45536
45537
|
}
|
|
45537
45538
|
|
|
45538
|
-
var version = "0.6.
|
|
45539
|
+
var version = "0.6.83";
|
|
45539
45540
|
|
|
45540
45541
|
// Parse command line args into commands and run them
|
|
45541
45542
|
// Function takes an optional Node-style callback. A Promise is returned if no callback is given.
|
package/package.json
CHANGED
package/www/index.html
CHANGED
|
@@ -183,9 +183,9 @@ precision=0.001. Click to see all options.</div></div></div></a>
|
|
|
183
183
|
<div class="info-box">
|
|
184
184
|
<div class="close2-btn"></div>
|
|
185
185
|
<h3>Basemap options</h3>
|
|
186
|
-
<p class="basemap-note"
|
|
186
|
+
<p class="basemap-note"></p>
|
|
187
187
|
<p class="basemap-warning"></p>
|
|
188
|
-
<div class="basemap-styles"></div>
|
|
188
|
+
<div class="basemap-styles basemap-buttons"></div>
|
|
189
189
|
<div>
|
|
190
190
|
<!-- <div class="close-btn btn dialog-btn">Close</div> -->
|
|
191
191
|
<div class="clear-btn btn dialog-btn disabled">Clear</div>
|
|
@@ -298,8 +298,8 @@ encoding=big5</span>. Click to see all options.</div></div></div></div>
|
|
|
298
298
|
<span class="intersection-check text-btn colored-text">Check line intersections</span><span class="intersection-count">0 line intersections</span>
|
|
299
299
|
<img class="close-btn" draggable="false" src="images/close.png">
|
|
300
300
|
<div class="repair-btn text-btn colored-text">Repair</div>
|
|
301
|
-
|
|
302
301
|
</div>
|
|
302
|
+
<div class="basemap-overlay-buttons basemap-buttons"></div>
|
|
303
303
|
<div class="map-layers"></div>
|
|
304
304
|
<div class="basemap-container"><div class="basemap"></div></div>
|
|
305
305
|
</div>
|
package/www/mapshaper-gui.js
CHANGED
|
@@ -2564,18 +2564,6 @@
|
|
|
2564
2564
|
return isProjectedLayer(lyr) ? lyr.gui.invertPoint(p[0], p[1]) : p;
|
|
2565
2565
|
}
|
|
2566
2566
|
|
|
2567
|
-
// bbox: display coords
|
|
2568
|
-
// intended to work with rectangular projections like Mercator
|
|
2569
|
-
function getBBoxCoords(lyr, bbox) {
|
|
2570
|
-
if (!isProjectedLayer(lyr)) return bbox.concat();
|
|
2571
|
-
var a = translateDisplayPoint(lyr, [bbox[0], bbox[1]]);
|
|
2572
|
-
var b = translateDisplayPoint(lyr, [bbox[2], bbox[3]]);
|
|
2573
|
-
var bounds = new internal.Bounds();
|
|
2574
|
-
bounds.mergePoint(a[0], a[1]);
|
|
2575
|
-
bounds.mergePoint(b[0], b[1]);
|
|
2576
|
-
return bounds.toArray();
|
|
2577
|
-
}
|
|
2578
|
-
|
|
2579
2567
|
function isProjectedLayer(lyr) {
|
|
2580
2568
|
return !!lyr?.gui.invertPoint;
|
|
2581
2569
|
}
|
|
@@ -3425,7 +3413,7 @@
|
|
|
3425
3413
|
//
|
|
3426
3414
|
function pointExceedsTolerance(p, points, tolerance) {
|
|
3427
3415
|
if (points.length < 2) return false;
|
|
3428
|
-
var p1 = points[0], p2, dist;
|
|
3416
|
+
var p1 = points[0], p2, dist, angle;
|
|
3429
3417
|
for (var i=1; i<points.length; i++) {
|
|
3430
3418
|
p2 = points[i];
|
|
3431
3419
|
dist = Math.sqrt(geom.pointSegDistSq(p2[0], p2[1], p1[0], p1[1], p[0], p[1]));
|
|
@@ -3434,6 +3422,15 @@
|
|
|
3434
3422
|
return false;
|
|
3435
3423
|
}
|
|
3436
3424
|
|
|
3425
|
+
function getAvgPoint(points) {
|
|
3426
|
+
var x=0, y=0;
|
|
3427
|
+
for (var i=0; i<points.length; i++) {
|
|
3428
|
+
x += points[i][0];
|
|
3429
|
+
y += points[i][1];
|
|
3430
|
+
}
|
|
3431
|
+
return [x/points.length, y/points.length];
|
|
3432
|
+
}
|
|
3433
|
+
|
|
3437
3434
|
function setZ(lyr, z) {
|
|
3438
3435
|
lyr.gui.source.dataset.arcs.setRetainedInterval(z);
|
|
3439
3436
|
if (isProjectedLayer(lyr)) {
|
|
@@ -8065,7 +8062,6 @@
|
|
|
8065
8062
|
var transientIds = []; // e.g. hit ids while dragging a box
|
|
8066
8063
|
var drawingId = -1; // kludge to allow hit detection and drawing (different feature ids)
|
|
8067
8064
|
var active = false;
|
|
8068
|
-
var interactionMode;
|
|
8069
8065
|
var targetLayer;
|
|
8070
8066
|
var hitTest;
|
|
8071
8067
|
var pinnedOn; // used in multi-edit mode (selection) for toggling pinning behavior
|
|
@@ -8075,16 +8071,11 @@
|
|
|
8075
8071
|
var priority = 2;
|
|
8076
8072
|
|
|
8077
8073
|
mouse.on('contextmenu', function(e) {
|
|
8078
|
-
// shift key enables default menu (for development)
|
|
8079
|
-
if (gui.keyboard.shiftIsPressed()) {
|
|
8080
|
-
return;
|
|
8081
|
-
}
|
|
8082
8074
|
e.originalEvent.preventDefault();
|
|
8083
|
-
if (
|
|
8084
|
-
|
|
8075
|
+
if (El('body').hasClass('map-view')) {
|
|
8076
|
+
triggerHitEvent('contextmenu', e);
|
|
8085
8077
|
}
|
|
8086
|
-
|
|
8087
|
-
}, false);
|
|
8078
|
+
});
|
|
8088
8079
|
|
|
8089
8080
|
// init keyboard controls for pinned features
|
|
8090
8081
|
gui.keyboard.on('keydown', function(evt) {
|
|
@@ -8126,11 +8117,14 @@
|
|
|
8126
8117
|
};
|
|
8127
8118
|
|
|
8128
8119
|
function updateHitTest(featureFilter) {
|
|
8129
|
-
hitTest = getPointerHitTest(targetLayer, ext, interactionMode, featureFilter);
|
|
8120
|
+
hitTest = getPointerHitTest(targetLayer, ext, interactionMode(), featureFilter);
|
|
8121
|
+
}
|
|
8122
|
+
|
|
8123
|
+
function interactionMode() {
|
|
8124
|
+
return gui.interaction.getMode();
|
|
8130
8125
|
}
|
|
8131
8126
|
|
|
8132
8127
|
function turnOn(mode) {
|
|
8133
|
-
interactionMode = mode;
|
|
8134
8128
|
active = true;
|
|
8135
8129
|
updateHitTest();
|
|
8136
8130
|
}
|
|
@@ -8145,12 +8139,8 @@
|
|
|
8145
8139
|
}
|
|
8146
8140
|
}
|
|
8147
8141
|
|
|
8148
|
-
function hoverable() {
|
|
8149
|
-
return !!interactionMode;
|
|
8150
|
-
}
|
|
8151
|
-
|
|
8152
8142
|
function selectable() {
|
|
8153
|
-
return interactionMode == 'selection';
|
|
8143
|
+
return interactionMode() == 'selection';
|
|
8154
8144
|
}
|
|
8155
8145
|
|
|
8156
8146
|
function pinnable() {
|
|
@@ -8159,16 +8149,16 @@
|
|
|
8159
8149
|
}
|
|
8160
8150
|
|
|
8161
8151
|
function draggable() {
|
|
8162
|
-
|
|
8163
|
-
|
|
8164
|
-
|
|
8152
|
+
var mode = interactionMode();
|
|
8153
|
+
return mode == 'vertices' || mode == 'edit_points' ||
|
|
8154
|
+
mode == 'labels' || mode == 'edit_lines' || mode == 'edit_polygons';
|
|
8165
8155
|
}
|
|
8166
8156
|
|
|
8167
8157
|
function clickable() {
|
|
8158
|
+
var mode = interactionMode();
|
|
8168
8159
|
// click used to pin popup and select features
|
|
8169
|
-
return
|
|
8170
|
-
|
|
8171
|
-
interactionMode == 'edit_points';
|
|
8160
|
+
return mode == 'data' || mode == 'info' || mode == 'selection' ||
|
|
8161
|
+
mode == 'rectangles' || mode == 'edit_points';
|
|
8172
8162
|
}
|
|
8173
8163
|
|
|
8174
8164
|
self.getHitId = function() {
|
|
@@ -8293,7 +8283,6 @@
|
|
|
8293
8283
|
// (some modes do not support pinning)
|
|
8294
8284
|
gui.on('interaction_mode_change', function(e) {
|
|
8295
8285
|
self.clearSelection();
|
|
8296
|
-
// if (e.mode == 'off' || e.mode == 'box') {
|
|
8297
8286
|
if (gui.interaction.modeUsesHitDetection(e.mode)) {
|
|
8298
8287
|
turnOn(e.mode);
|
|
8299
8288
|
} else {
|
|
@@ -8326,7 +8315,7 @@
|
|
|
8326
8315
|
updateSelectionState(convertClickDataToSelectionData(hitTest(e)));
|
|
8327
8316
|
}
|
|
8328
8317
|
|
|
8329
|
-
if (pinned && interactionMode == 'edit_points') {
|
|
8318
|
+
if (pinned && interactionMode() == 'edit_points') {
|
|
8330
8319
|
// kludge: intercept the click event if popup is turning off, so
|
|
8331
8320
|
// a new point doesn't get made
|
|
8332
8321
|
return;
|
|
@@ -8451,6 +8440,7 @@
|
|
|
8451
8440
|
|
|
8452
8441
|
// check if an event is used in the current interaction mode
|
|
8453
8442
|
function eventIsEnabled(type) {
|
|
8443
|
+
var mode = interactionMode();
|
|
8454
8444
|
if (!active) return false;
|
|
8455
8445
|
if (type == 'click' && gui.keyboard.ctrlIsPressed()) {
|
|
8456
8446
|
return false; // don't fire if context menu might open
|
|
@@ -8459,13 +8449,13 @@
|
|
|
8459
8449
|
return false;
|
|
8460
8450
|
}
|
|
8461
8451
|
if (type == 'click' &&
|
|
8462
|
-
(
|
|
8452
|
+
(mode == 'edit_lines' || mode == 'edit_polygons')) {
|
|
8463
8453
|
return true; // click events are triggered even if no shape is hit
|
|
8464
8454
|
}
|
|
8465
|
-
if (type == 'click' &&
|
|
8455
|
+
if (type == 'click' && mode == 'edit_points') {
|
|
8466
8456
|
return true;
|
|
8467
8457
|
}
|
|
8468
|
-
if ((
|
|
8458
|
+
if ((mode == 'edit_lines' || mode == 'edit_polygons') &&
|
|
8469
8459
|
(type == 'hover' || type == 'dblclick')) {
|
|
8470
8460
|
return true; // special case -- using hover for line drawing animation
|
|
8471
8461
|
}
|
|
@@ -8486,7 +8476,7 @@
|
|
|
8486
8476
|
}
|
|
8487
8477
|
|
|
8488
8478
|
function possiblyStopPropagation(e) {
|
|
8489
|
-
if (interactionMode == 'edit_lines' || interactionMode == 'edit_polygons') {
|
|
8479
|
+
if (interactionMode() == 'edit_lines' || interactionMode() == 'edit_polygons') {
|
|
8490
8480
|
// handled conditionally in the control
|
|
8491
8481
|
return;
|
|
8492
8482
|
}
|
|
@@ -8503,7 +8493,7 @@
|
|
|
8503
8493
|
// evt: event data (may be a pointer event object, an ordinary object or null)
|
|
8504
8494
|
function triggerHitEvent(type, evt) {
|
|
8505
8495
|
var eventData = {
|
|
8506
|
-
mode: interactionMode
|
|
8496
|
+
mode: interactionMode()
|
|
8507
8497
|
};
|
|
8508
8498
|
if (evt) {
|
|
8509
8499
|
// data coordinates
|
|
@@ -8822,6 +8812,11 @@
|
|
|
8822
8812
|
element.addEventListener('mousedown', onAreaDown);
|
|
8823
8813
|
element.addEventListener('dblclick', onAreaDblClick);
|
|
8824
8814
|
document.addEventListener('contextmenu', function(e) {
|
|
8815
|
+
if (!e.ctrlKey) {
|
|
8816
|
+
e.preventDefault();
|
|
8817
|
+
}
|
|
8818
|
+
});
|
|
8819
|
+
element.addEventListener('contextmenu', function(e) {
|
|
8825
8820
|
_self.dispatchEvent('contextmenu', procMouseEvent(e));
|
|
8826
8821
|
});
|
|
8827
8822
|
|
|
@@ -9099,9 +9094,9 @@
|
|
|
9099
9094
|
|
|
9100
9095
|
box.getDataCoords = function() {
|
|
9101
9096
|
if (!boxCoords) return null;
|
|
9102
|
-
var
|
|
9097
|
+
var lyr = gui.map.getActiveLayer();
|
|
9098
|
+
var dataBox = lyr ? translateCoordsToLayerCRS(boxCoords, lyr) : translateCoordsToLatLon(boxCoords);
|
|
9103
9099
|
fixBounds(dataBox);
|
|
9104
|
-
// return internal.getRoundedCoords(dataBox, internal.getBoundsPrecisionForDisplay(dataBox));
|
|
9105
9100
|
return dataBox;
|
|
9106
9101
|
};
|
|
9107
9102
|
|
|
@@ -9136,6 +9131,26 @@
|
|
|
9136
9131
|
}
|
|
9137
9132
|
};
|
|
9138
9133
|
|
|
9134
|
+
function translateCoordsToLatLon(bbox) {
|
|
9135
|
+
var crs = gui.map.getDisplayCRS();
|
|
9136
|
+
var a = internal.toLngLat([bbox[0], bbox[1]], crs);
|
|
9137
|
+
var b = internal.toLngLat([bbox[2], bbox[3]], crs);
|
|
9138
|
+
return a.concat(b);
|
|
9139
|
+
}
|
|
9140
|
+
|
|
9141
|
+
// bbox: display coords
|
|
9142
|
+
// intended to work with rectangular projections like Mercator
|
|
9143
|
+
function translateCoordsToLayerCRS(bbox, lyr) {
|
|
9144
|
+
if (!isProjectedLayer(lyr)) return bbox.concat();
|
|
9145
|
+
var a = translateDisplayPoint(lyr, [bbox[0], bbox[1]]);
|
|
9146
|
+
var b = translateDisplayPoint(lyr, [bbox[2], bbox[3]]);
|
|
9147
|
+
var bounds = new internal.Bounds();
|
|
9148
|
+
bounds.mergePoint(a[0], a[1]);
|
|
9149
|
+
bounds.mergePoint(b[0], b[1]);
|
|
9150
|
+
return bounds.toArray();
|
|
9151
|
+
}
|
|
9152
|
+
|
|
9153
|
+
// get bbox coords in the display CRS
|
|
9139
9154
|
function getBoxCoords(e) {
|
|
9140
9155
|
var bbox = pixToCoords(e.a.concat(e.b), gui.map.getExtent());
|
|
9141
9156
|
fixBounds(bbox);
|
|
@@ -9236,6 +9251,7 @@
|
|
|
9236
9251
|
zoomBox = new HighlightBox(gui, {draggable: true, name: 'zoom-box'}), // .addClass('zooming'),
|
|
9237
9252
|
shiftDrag = false,
|
|
9238
9253
|
zoomScaleMultiplier = 1,
|
|
9254
|
+
panCount = 0,
|
|
9239
9255
|
inBtn, outBtn,
|
|
9240
9256
|
dragStartEvt,
|
|
9241
9257
|
_fx, _fy; // zoom foci, [0,1]
|
|
@@ -9287,18 +9303,11 @@
|
|
|
9287
9303
|
// var lyr = gui.model.getActiveLayer()?.layer;
|
|
9288
9304
|
// if (lyr && !internal.layerHasGeometry(lyr)) return;
|
|
9289
9305
|
shiftDrag = !!e.shiftKey;
|
|
9306
|
+
panCount = 0;
|
|
9290
9307
|
if (shiftDrag) {
|
|
9291
9308
|
if (useBoxZoom()) zoomBox.turnOn();
|
|
9292
9309
|
dragStartEvt = e;
|
|
9293
9310
|
gui.dispatchEvent('shift_drag_start');
|
|
9294
|
-
} else {
|
|
9295
|
-
El('body').addClass('pan');
|
|
9296
|
-
setTimeout(function() {
|
|
9297
|
-
var body = El('body');
|
|
9298
|
-
if (body.hasClass('pan')) {
|
|
9299
|
-
body.addClass('panning');
|
|
9300
|
-
}
|
|
9301
|
-
}, 100);
|
|
9302
9311
|
}
|
|
9303
9312
|
});
|
|
9304
9313
|
|
|
@@ -9306,9 +9315,18 @@
|
|
|
9306
9315
|
if (disabled()) return;
|
|
9307
9316
|
if (shiftDrag) {
|
|
9308
9317
|
gui.dispatchEvent('shift_drag', getBoxData(e));
|
|
9309
|
-
|
|
9310
|
-
|
|
9318
|
+
return;
|
|
9319
|
+
}
|
|
9320
|
+
if (++panCount == 1) {
|
|
9321
|
+
El('body').addClass('pan');
|
|
9322
|
+
setTimeout(function() {
|
|
9323
|
+
var body = El('body');
|
|
9324
|
+
if (body.hasClass('pan')) {
|
|
9325
|
+
body.addClass('panning');
|
|
9326
|
+
}
|
|
9327
|
+
}, 100);
|
|
9311
9328
|
}
|
|
9329
|
+
ext.pan(e.dx, e.dy);
|
|
9312
9330
|
});
|
|
9313
9331
|
|
|
9314
9332
|
mouse.on('dragend', function(e) {
|
|
@@ -10323,7 +10341,7 @@
|
|
|
10323
10341
|
}
|
|
10324
10342
|
|
|
10325
10343
|
function pencilIsActive() {
|
|
10326
|
-
return active() && (cmdKeyDown() || pathDrawing()) && !vertexDragging();
|
|
10344
|
+
return active() && (cmdKeyDown() || pathDrawing()) && !vertexDragging() && !!pencilPoints;
|
|
10327
10345
|
}
|
|
10328
10346
|
|
|
10329
10347
|
function polygonMode() {
|
|
@@ -10521,7 +10539,7 @@
|
|
|
10521
10539
|
}
|
|
10522
10540
|
e.stopPropagation(); // prevent panning
|
|
10523
10541
|
hoverVertexInfo = findPathStartInfo(e);
|
|
10524
|
-
var xy = [e.x, e.y];
|
|
10542
|
+
var xy = [e.x, e.y], xy2;
|
|
10525
10543
|
var p = pixToDataCoords(e.x, e.y);
|
|
10526
10544
|
if (!pathDrawing()) {
|
|
10527
10545
|
pencilPoints = [xy];
|
|
@@ -10530,17 +10548,20 @@
|
|
|
10530
10548
|
// start pencil-drawing when a path is started
|
|
10531
10549
|
pencilPoints = [xy];
|
|
10532
10550
|
extendCurrentPath(p);
|
|
10533
|
-
} else if (hoverVertexInfo && pencilPoints.length > 2) {
|
|
10551
|
+
} else if (polygonMode() && hoverVertexInfo && pencilPoints.length > 2) {
|
|
10534
10552
|
// close path
|
|
10535
10553
|
p = hoverVertexInfo.point;
|
|
10536
10554
|
appendVertex$1(hit.getHitTarget(), p);
|
|
10537
10555
|
extendCurrentPath(p);
|
|
10538
10556
|
pencilPoints = null; // stop drawing
|
|
10539
|
-
} else if (pointExceedsTolerance(xy, pencilPoints, 1.
|
|
10540
|
-
|
|
10541
|
-
p = pixToDataCoords(
|
|
10542
|
-
pencilPoints = [xy];
|
|
10557
|
+
} else if (pencilPoints.length >= 2 && pointExceedsTolerance(xy, pencilPoints, 1.4)) {
|
|
10558
|
+
xy2 = pencilPoints.pop();
|
|
10559
|
+
p = pixToDataCoords(xy2[0], xy2[1]);
|
|
10543
10560
|
extendCurrentPath(p);
|
|
10561
|
+
// kludgy way to get a smoother line (could be better)
|
|
10562
|
+
// not this pencilPoints = [getAvgPoint(pencilPoints), xy2, xy];
|
|
10563
|
+
// not this pencilPoints = pencilPoints.slice(-2).concat([xy2, xy]);
|
|
10564
|
+
pencilPoints = [getAvgPoint(pencilPoints.slice(-3).concat([xy2])), xy2, xy];
|
|
10544
10565
|
} else {
|
|
10545
10566
|
// skip this point, update the hover line
|
|
10546
10567
|
pencilPoints.push(xy);
|
|
@@ -12305,373 +12326,107 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
12305
12326
|
}
|
|
12306
12327
|
}
|
|
12307
12328
|
|
|
12308
|
-
|
|
12309
|
-
var script = document.createElement('script');
|
|
12310
|
-
script.onload = cb;
|
|
12311
|
-
script.src = url;
|
|
12312
|
-
document.head.appendChild(script);
|
|
12313
|
-
}
|
|
12314
|
-
|
|
12315
|
-
function loadStylesheet(url) {
|
|
12316
|
-
var el = document.createElement('link');
|
|
12317
|
-
el.rel = 'stylesheet';
|
|
12318
|
-
el.type = 'text/css';
|
|
12319
|
-
el.media = 'screen';
|
|
12320
|
-
el.href = url;
|
|
12321
|
-
document.head.appendChild(el);
|
|
12322
|
-
}
|
|
12323
|
-
|
|
12324
|
-
function Basemap(gui, ext) {
|
|
12325
|
-
var menu = gui.container.findChild('.basemap-options');
|
|
12326
|
-
// var hideBtn = new SimpleButton(menu.findChild('.hide-btn'));
|
|
12327
|
-
var fadeBtn = new SimpleButton(menu.findChild('.fade-btn'));
|
|
12328
|
-
var closeBtn = new SimpleButton(menu.findChild('.close2-btn'));
|
|
12329
|
-
var clearBtn = new SimpleButton(menu.findChild('.clear-btn'));
|
|
12330
|
-
var list = menu.findChild('.basemap-styles');
|
|
12331
|
-
var container = gui.container.findChild('.basemap-container');
|
|
12332
|
-
var basemapBtn = gui.container.findChild('.basemap-btn');
|
|
12333
|
-
var basemapNote = gui.container.findChild('.basemap-note');
|
|
12334
|
-
var basemapWarning = gui.container.findChild('.basemap-warning');
|
|
12335
|
-
var mapEl = gui.container.findChild('.basemap');
|
|
12336
|
-
var extentNote = El('div').addClass('basemap-prompt').appendTo(container).hide();
|
|
12337
|
-
var params = window.mapboxParams;
|
|
12338
|
-
var map;
|
|
12339
|
-
var activeStyle;
|
|
12340
|
-
var loading = false;
|
|
12341
|
-
var faded = false;
|
|
12342
|
-
|
|
12343
|
-
if (params) {
|
|
12344
|
-
// TODO: check page URL for compatibility with mapbox key
|
|
12345
|
-
init();
|
|
12346
|
-
} else {
|
|
12347
|
-
basemapBtn.hide();
|
|
12348
|
-
}
|
|
12329
|
+
utils$1.inherit(MshpMap, EventDispatcher);
|
|
12349
12330
|
|
|
12350
|
-
|
|
12351
|
-
|
|
12331
|
+
function MshpMap(gui) {
|
|
12332
|
+
var opts = gui.options,
|
|
12333
|
+
el = gui.container.findChild('.map-layers').node(),
|
|
12334
|
+
position = new ElementPosition(el),
|
|
12335
|
+
model = gui.model,
|
|
12336
|
+
map = this,
|
|
12337
|
+
_mouse = new MouseArea(el, position),
|
|
12338
|
+
_ext = new MapExtent(position),
|
|
12339
|
+
_nav = new MapNav(gui, _ext, _mouse),
|
|
12340
|
+
_visibleLayers = [], // cached visible map layers
|
|
12341
|
+
_hit,
|
|
12342
|
+
_intersectionLyr, _activeLyr, _overlayLyr,
|
|
12343
|
+
_renderer, _dynamicCRS;
|
|
12352
12344
|
|
|
12353
|
-
|
|
12354
|
-
gui.clearMode();
|
|
12355
|
-
turnOff();
|
|
12356
|
-
});
|
|
12345
|
+
_mouse.disable(); // wait for gui.focus() to activate mouse events
|
|
12357
12346
|
|
|
12358
|
-
|
|
12359
|
-
|
|
12360
|
-
|
|
12361
|
-
|
|
12362
|
-
closeMenu();
|
|
12363
|
-
}
|
|
12364
|
-
});
|
|
12347
|
+
model.on('select', function(e) {
|
|
12348
|
+
_intersectionLyr = null;
|
|
12349
|
+
_overlayLyr = null;
|
|
12350
|
+
});
|
|
12365
12351
|
|
|
12366
|
-
|
|
12367
|
-
|
|
12368
|
-
|
|
12369
|
-
faded = false;
|
|
12370
|
-
fadeBtn.text('Fade');
|
|
12371
|
-
} else if (activeStyle) {
|
|
12372
|
-
mapEl.css('opacity', 0.35);
|
|
12373
|
-
faded = true;
|
|
12374
|
-
fadeBtn.text('Unfade');
|
|
12375
|
-
}
|
|
12376
|
-
});
|
|
12352
|
+
gui.on('active', function() {
|
|
12353
|
+
_mouse.enable();
|
|
12354
|
+
});
|
|
12377
12355
|
|
|
12378
|
-
|
|
12379
|
-
|
|
12380
|
-
|
|
12381
|
-
});
|
|
12356
|
+
gui.on('inactive', function() {
|
|
12357
|
+
_mouse.disable();
|
|
12358
|
+
});
|
|
12382
12359
|
|
|
12383
|
-
|
|
12384
|
-
|
|
12385
|
-
|
|
12386
|
-
if (style == activeStyle) {
|
|
12387
|
-
turnOffBasemap();
|
|
12388
|
-
} else {
|
|
12389
|
-
showBasemap(style);
|
|
12390
|
-
}
|
|
12391
|
-
updateButtons();
|
|
12392
|
-
closeMenu();
|
|
12393
|
-
});
|
|
12394
|
-
btn.appendTo(list);
|
|
12395
|
-
});
|
|
12396
|
-
}
|
|
12360
|
+
gui.on('map-needs-refresh', function() {
|
|
12361
|
+
drawLayers();
|
|
12362
|
+
});
|
|
12397
12363
|
|
|
12398
|
-
|
|
12399
|
-
function closeMenu() {
|
|
12400
|
-
setTimeout(function() {
|
|
12401
|
-
gui.clearMode();
|
|
12402
|
-
}, 200);
|
|
12403
|
-
}
|
|
12364
|
+
model.on('update', onUpdate);
|
|
12404
12365
|
|
|
12405
|
-
function
|
|
12406
|
-
|
|
12407
|
-
|
|
12408
|
-
|
|
12409
|
-
}
|
|
12366
|
+
document.addEventListener('visibilitychange', function(e) {
|
|
12367
|
+
// refresh map when browser tab is re-activated (Chrome on mac has been
|
|
12368
|
+
// blanking the canvas after several other tabs are visited)
|
|
12369
|
+
if (document.visibilityState == 'visible') drawLayers();
|
|
12370
|
+
});
|
|
12410
12371
|
|
|
12411
|
-
|
|
12412
|
-
|
|
12413
|
-
|
|
12414
|
-
|
|
12415
|
-
|
|
12416
|
-
|
|
12417
|
-
|
|
12418
|
-
|
|
12419
|
-
|
|
12420
|
-
initMap();
|
|
12372
|
+
// Update display of segment intersections
|
|
12373
|
+
this.setIntersectionLayer = function(lyr, dataset) {
|
|
12374
|
+
if (lyr == _intersectionLyr) return; // no change
|
|
12375
|
+
if (lyr) {
|
|
12376
|
+
enhanceLayerForDisplay(lyr, dataset, getDisplayOptions());
|
|
12377
|
+
_intersectionLyr = lyr;
|
|
12378
|
+
_intersectionLyr.gui.style = getIntersectionStyle(_intersectionLyr.gui.displayLayer, getGlobalStyleOptions());
|
|
12379
|
+
} else {
|
|
12380
|
+
_intersectionLyr = null;
|
|
12421
12381
|
}
|
|
12422
|
-
|
|
12423
|
-
|
|
12424
|
-
|
|
12425
|
-
list.findChildren('.basemap-style-btn').forEach(function(el, i) {
|
|
12426
|
-
el.classed('active', params.styles[i] == activeStyle);
|
|
12427
|
-
});
|
|
12428
|
-
}
|
|
12382
|
+
// TODO: try to avoid redrawing layers twice (in some situations)
|
|
12383
|
+
drawLayers();
|
|
12384
|
+
};
|
|
12429
12385
|
|
|
12430
|
-
function
|
|
12431
|
-
|
|
12432
|
-
|
|
12433
|
-
var info = getDatasetCrsInfo(activeLyr?.dataset); // defaults to wgs84
|
|
12434
|
-
var dataCRS = info.crs || null;
|
|
12435
|
-
var displayCRS = gui.map.getDisplayCRS();
|
|
12436
|
-
var warning;
|
|
12386
|
+
this.setLayerPinning = function(target, pinned) {
|
|
12387
|
+
target.layer.pinned = !!pinned;
|
|
12388
|
+
};
|
|
12437
12389
|
|
|
12438
|
-
|
|
12439
|
-
|
|
12440
|
-
|
|
12441
|
-
|
|
12442
|
-
|
|
12443
|
-
warning += ' Reason: unknown projection.';
|
|
12444
|
-
}
|
|
12390
|
+
this.translatePixelCoords = function(x, y) {
|
|
12391
|
+
var p = _ext.translatePixelCoords(x, y);
|
|
12392
|
+
if (!_dynamicCRS) return p;
|
|
12393
|
+
return internal.toLngLat(p, _dynamicCRS);
|
|
12394
|
+
};
|
|
12445
12395
|
|
|
12446
|
-
|
|
12447
|
-
|
|
12448
|
-
|
|
12449
|
-
|
|
12396
|
+
this.pixelCoordsToDisplayCoords = function(x, y) {
|
|
12397
|
+
var p1 = _ext.translatePixelCoords(x, y);
|
|
12398
|
+
var p2 = _ext.translatePixelCoords(x+1, y+1);
|
|
12399
|
+
var crs = this.getDisplayCRS();
|
|
12400
|
+
if (crs) {
|
|
12401
|
+
p1 = internal.toLngLat(p1, crs) || p1;
|
|
12402
|
+
p2 = internal.toLngLat(p2, crs) || p2;
|
|
12450
12403
|
}
|
|
12451
|
-
|
|
12452
|
-
}
|
|
12404
|
+
return formatCoordsForDisplay(p1, p2);
|
|
12405
|
+
};
|
|
12453
12406
|
|
|
12454
|
-
function
|
|
12455
|
-
|
|
12456
|
-
|
|
12457
|
-
|
|
12458
|
-
|
|
12407
|
+
// this.getCenterLngLat = function() {
|
|
12408
|
+
// var bounds = _ext.getBounds();
|
|
12409
|
+
// var crs = this.getDisplayCRS();
|
|
12410
|
+
// // TODO: handle case where active layer is a frame layer
|
|
12411
|
+
// if (!bounds.hasBounds() || !crs) {
|
|
12412
|
+
// return null;
|
|
12413
|
+
// }
|
|
12414
|
+
// return internal.toLngLat([bounds.centerX(), bounds.centerY()], crs);
|
|
12415
|
+
// };
|
|
12459
12416
|
|
|
12460
|
-
function
|
|
12461
|
-
|
|
12462
|
-
|
|
12463
|
-
|
|
12464
|
-
|
|
12465
|
-
|
|
12466
|
-
|
|
12467
|
-
|
|
12468
|
-
|
|
12469
|
-
|
|
12470
|
-
gui.
|
|
12471
|
-
|
|
12472
|
-
}
|
|
12473
|
-
|
|
12474
|
-
function getLonLatBounds() {
|
|
12475
|
-
var bbox = ext.getBounds().toArray();
|
|
12476
|
-
var bbox2 = fromWebMercator(bbox[0], bbox[1])
|
|
12477
|
-
.concat(fromWebMercator(bbox[2], bbox[3]));
|
|
12478
|
-
return bbox2;
|
|
12479
|
-
}
|
|
12480
|
-
|
|
12481
|
-
function initMap() {
|
|
12482
|
-
if (!enabled() || map || loading) return;
|
|
12483
|
-
loading = true;
|
|
12484
|
-
loadStylesheet(params.css);
|
|
12485
|
-
loadScript(params.js, function() {
|
|
12486
|
-
map = new window.mapboxgl.Map({
|
|
12487
|
-
accessToken: params.key,
|
|
12488
|
-
logoPosition: 'bottom-left',
|
|
12489
|
-
container: mapEl.node(),
|
|
12490
|
-
style: activeStyle.url,
|
|
12491
|
-
bounds: getLonLatBounds(),
|
|
12492
|
-
doubleClickZoom: false,
|
|
12493
|
-
dragPan: false,
|
|
12494
|
-
dragRotate: false,
|
|
12495
|
-
scrollZoom: false,
|
|
12496
|
-
interactive: false,
|
|
12497
|
-
keyboard: false,
|
|
12498
|
-
maxPitch: 0,
|
|
12499
|
-
renderWorldCopies: true // false // false prevents panning off the map
|
|
12500
|
-
});
|
|
12501
|
-
map.on('load', function() {
|
|
12502
|
-
loading = false;
|
|
12503
|
-
refresh();
|
|
12504
|
-
});
|
|
12505
|
-
});
|
|
12506
|
-
}
|
|
12507
|
-
|
|
12508
|
-
// @bbox: latlon bounding box of current map extent
|
|
12509
|
-
function checkBounds(bbox) {
|
|
12510
|
-
var mpp = ext.getBounds().width() / ext.width();
|
|
12511
|
-
var z = scaleToZoom(mpp);
|
|
12512
|
-
var msg;
|
|
12513
|
-
if (bbox[1] >= -85 && bbox[3] <= 85 && z <= 20) {
|
|
12514
|
-
extentNote.hide();
|
|
12515
|
-
return true;
|
|
12516
|
-
}
|
|
12517
|
-
if (z > 20) {
|
|
12518
|
-
msg = 'zoom out';
|
|
12519
|
-
} else if (bbox[1] > 0) {
|
|
12520
|
-
msg = 'pan south';
|
|
12521
|
-
} else if (bbox[3] < 0) {
|
|
12522
|
-
msg = 'pan north';
|
|
12523
|
-
} else {
|
|
12524
|
-
msg = msg = 'zoom in';
|
|
12525
|
-
}
|
|
12526
|
-
extentNote.html(msg + ' to see the basemap').show();
|
|
12527
|
-
return false;
|
|
12528
|
-
}
|
|
12529
|
-
|
|
12530
|
-
function crsIsUsable(crs) {
|
|
12531
|
-
if (!crs) return false;
|
|
12532
|
-
if (!internal.isInvertibleCRS(crs)) return false;
|
|
12533
|
-
return true;
|
|
12534
|
-
}
|
|
12535
|
-
|
|
12536
|
-
function prepareMapView() {
|
|
12537
|
-
var crs = gui.map.getDisplayCRS();
|
|
12538
|
-
if (!crs) return false;
|
|
12539
|
-
if (!internal.isWebMercator(crs)) {
|
|
12540
|
-
gui.map.setDisplayCRS(internal.parseCrsString('webmercator'));
|
|
12541
|
-
}
|
|
12542
|
-
return true;
|
|
12543
|
-
}
|
|
12544
|
-
|
|
12545
|
-
function refresh() {
|
|
12546
|
-
var crs = gui.map.getDisplayCRS();
|
|
12547
|
-
var off = !crs || !enabled() || !map || loading || !activeStyle;
|
|
12548
|
-
fadeBtn.active(!off);
|
|
12549
|
-
clearBtn.active(!off);
|
|
12550
|
-
if (off) {
|
|
12551
|
-
hide();
|
|
12552
|
-
extentNote.hide();
|
|
12553
|
-
return;
|
|
12554
|
-
}
|
|
12555
|
-
|
|
12556
|
-
prepareMapView();
|
|
12557
|
-
var bbox = getLonLatBounds();
|
|
12558
|
-
if (!checkBounds(bbox)) {
|
|
12559
|
-
// map does not display outside these bounds
|
|
12560
|
-
hide();
|
|
12561
|
-
} else {
|
|
12562
|
-
show();
|
|
12563
|
-
map.resize();
|
|
12564
|
-
map.fitBounds(bbox, {animate: false});
|
|
12565
|
-
}
|
|
12566
|
-
}
|
|
12567
|
-
|
|
12568
|
-
return {refresh: refresh}; // called by map when extent changes
|
|
12569
|
-
}
|
|
12570
|
-
|
|
12571
|
-
utils$1.inherit(MshpMap, EventDispatcher);
|
|
12572
|
-
|
|
12573
|
-
function MshpMap(gui) {
|
|
12574
|
-
var opts = gui.options,
|
|
12575
|
-
el = gui.container.findChild('.map-layers').node(),
|
|
12576
|
-
position = new ElementPosition(el),
|
|
12577
|
-
model = gui.model,
|
|
12578
|
-
map = this,
|
|
12579
|
-
_mouse = new MouseArea(el, position),
|
|
12580
|
-
_ext = new MapExtent(position),
|
|
12581
|
-
_nav = new MapNav(gui, _ext, _mouse),
|
|
12582
|
-
_visibleLayers = [], // cached visible map layers
|
|
12583
|
-
_hit,
|
|
12584
|
-
_basemap,
|
|
12585
|
-
_intersectionLyr, _activeLyr, _overlayLyr,
|
|
12586
|
-
_renderer, _dynamicCRS;
|
|
12587
|
-
|
|
12588
|
-
_basemap = new Basemap(gui, _ext);
|
|
12589
|
-
|
|
12590
|
-
_mouse.disable(); // wait for gui.focus() to activate mouse events
|
|
12591
|
-
|
|
12592
|
-
model.on('select', function(e) {
|
|
12593
|
-
_intersectionLyr = null;
|
|
12594
|
-
_overlayLyr = null;
|
|
12595
|
-
});
|
|
12596
|
-
|
|
12597
|
-
gui.on('active', function() {
|
|
12598
|
-
_mouse.enable();
|
|
12599
|
-
});
|
|
12600
|
-
|
|
12601
|
-
gui.on('inactive', function() {
|
|
12602
|
-
_mouse.disable();
|
|
12603
|
-
});
|
|
12604
|
-
|
|
12605
|
-
gui.on('map-needs-refresh', function() {
|
|
12606
|
-
drawLayers();
|
|
12607
|
-
});
|
|
12608
|
-
|
|
12609
|
-
model.on('update', onUpdate);
|
|
12610
|
-
|
|
12611
|
-
document.addEventListener('visibilitychange', function(e) {
|
|
12612
|
-
// refresh map when browser tab is re-activated (Chrome on mac has been
|
|
12613
|
-
// blanking the canvas after several other tabs are visited)
|
|
12614
|
-
if (document.visibilityState == 'visible') drawLayers();
|
|
12615
|
-
});
|
|
12616
|
-
|
|
12617
|
-
// Update display of segment intersections
|
|
12618
|
-
this.setIntersectionLayer = function(lyr, dataset) {
|
|
12619
|
-
if (lyr == _intersectionLyr) return; // no change
|
|
12620
|
-
if (lyr) {
|
|
12621
|
-
enhanceLayerForDisplay(lyr, dataset, getDisplayOptions());
|
|
12622
|
-
_intersectionLyr = lyr;
|
|
12623
|
-
_intersectionLyr.gui.style = getIntersectionStyle(_intersectionLyr.gui.displayLayer, getGlobalStyleOptions());
|
|
12624
|
-
} else {
|
|
12625
|
-
_intersectionLyr = null;
|
|
12626
|
-
}
|
|
12627
|
-
// TODO: try to avoid redrawing layers twice (in some situations)
|
|
12628
|
-
drawLayers();
|
|
12629
|
-
};
|
|
12630
|
-
|
|
12631
|
-
this.setLayerPinning = function(target, pinned) {
|
|
12632
|
-
target.layer.pinned = !!pinned;
|
|
12633
|
-
};
|
|
12634
|
-
|
|
12635
|
-
this.translatePixelCoords = function(x, y) {
|
|
12636
|
-
var p = _ext.translatePixelCoords(x, y);
|
|
12637
|
-
if (!_dynamicCRS) return p;
|
|
12638
|
-
return internal.toLngLat(p, _dynamicCRS);
|
|
12639
|
-
};
|
|
12640
|
-
|
|
12641
|
-
this.pixelCoordsToDisplayCoords = function(x, y) {
|
|
12642
|
-
var p1 = _ext.translatePixelCoords(x, y);
|
|
12643
|
-
var p2 = _ext.translatePixelCoords(x+1, y+1);
|
|
12644
|
-
var crs = this.getDisplayCRS();
|
|
12645
|
-
if (crs) {
|
|
12646
|
-
p1 = internal.toLngLat(p1, crs) || p1;
|
|
12647
|
-
p2 = internal.toLngLat(p2, crs) || p2;
|
|
12648
|
-
}
|
|
12649
|
-
return formatCoordsForDisplay(p1, p2);
|
|
12650
|
-
};
|
|
12651
|
-
|
|
12652
|
-
// this.getCenterLngLat = function() {
|
|
12653
|
-
// var bounds = _ext.getBounds();
|
|
12654
|
-
// var crs = this.getDisplayCRS();
|
|
12655
|
-
// // TODO: handle case where active layer is a frame layer
|
|
12656
|
-
// if (!bounds.hasBounds() || !crs) {
|
|
12657
|
-
// return null;
|
|
12658
|
-
// }
|
|
12659
|
-
// return internal.toLngLat([bounds.centerX(), bounds.centerY()], crs);
|
|
12660
|
-
// };
|
|
12661
|
-
|
|
12662
|
-
this.getDisplayCRS = function() {
|
|
12663
|
-
if (!_activeLyr) {
|
|
12664
|
-
return _dynamicCRS || internal.parseCrsString('wgs84');
|
|
12665
|
-
}
|
|
12666
|
-
if (!_activeLyr.gui.geographic) {
|
|
12667
|
-
return null;
|
|
12668
|
-
}
|
|
12669
|
-
if (_activeLyr.gui.dynamic_crs) {
|
|
12670
|
-
return _activeLyr.gui.dynamic_crs;
|
|
12671
|
-
}
|
|
12672
|
-
var info = getDatasetCrsInfo(_activeLyr.gui.source.dataset);
|
|
12673
|
-
return info.crs || null;
|
|
12674
|
-
};
|
|
12417
|
+
this.getDisplayCRS = function() {
|
|
12418
|
+
if (!_activeLyr) {
|
|
12419
|
+
return _dynamicCRS || internal.parseCrsString('wgs84');
|
|
12420
|
+
}
|
|
12421
|
+
if (!_activeLyr.gui.geographic) {
|
|
12422
|
+
return null;
|
|
12423
|
+
}
|
|
12424
|
+
if (_activeLyr.gui.dynamic_crs) {
|
|
12425
|
+
return _activeLyr.gui.dynamic_crs;
|
|
12426
|
+
}
|
|
12427
|
+
var info = getDatasetCrsInfo(_activeLyr.gui.source.dataset);
|
|
12428
|
+
return info.crs || null;
|
|
12429
|
+
};
|
|
12675
12430
|
|
|
12676
12431
|
this.getExtent = function() {return _ext;};
|
|
12677
12432
|
this.getMouse = function() {return _mouse;};
|
|
@@ -12737,7 +12492,7 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
12737
12492
|
}
|
|
12738
12493
|
|
|
12739
12494
|
_ext.on('change', function(e) {
|
|
12740
|
-
|
|
12495
|
+
gui?.basemap.refresh(); // keep basemap synced up (if enabled)
|
|
12741
12496
|
drawLayers(e.redraw ? '' : 'nav');
|
|
12742
12497
|
});
|
|
12743
12498
|
|
|
@@ -12816,7 +12571,7 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
12816
12571
|
|
|
12817
12572
|
if (needReset) {
|
|
12818
12573
|
_ext.reset();
|
|
12819
|
-
|
|
12574
|
+
gui?.basemap.refresh();
|
|
12820
12575
|
}
|
|
12821
12576
|
drawLayers();
|
|
12822
12577
|
map.dispatchEvent('updated');
|
|
@@ -13206,6 +12961,293 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13206
12961
|
return retn;
|
|
13207
12962
|
}
|
|
13208
12963
|
|
|
12964
|
+
function loadScript(url, cb) {
|
|
12965
|
+
var script = document.createElement('script');
|
|
12966
|
+
script.onload = cb;
|
|
12967
|
+
script.src = url;
|
|
12968
|
+
document.head.appendChild(script);
|
|
12969
|
+
}
|
|
12970
|
+
|
|
12971
|
+
function loadStylesheet(url) {
|
|
12972
|
+
var el = document.createElement('link');
|
|
12973
|
+
el.rel = 'stylesheet';
|
|
12974
|
+
el.type = 'text/css';
|
|
12975
|
+
el.media = 'screen';
|
|
12976
|
+
el.href = url;
|
|
12977
|
+
document.head.appendChild(el);
|
|
12978
|
+
}
|
|
12979
|
+
|
|
12980
|
+
function Basemap(gui) {
|
|
12981
|
+
var menu = gui.container.findChild('.basemap-options');
|
|
12982
|
+
var fadeBtn = new SimpleButton(menu.findChild('.fade-btn'));
|
|
12983
|
+
var closeBtn = new SimpleButton(menu.findChild('.close2-btn'));
|
|
12984
|
+
var clearBtn = new SimpleButton(menu.findChild('.clear-btn'));
|
|
12985
|
+
var menuButtons = menu.findChild('.basemap-styles');
|
|
12986
|
+
var overlayButtons = gui.container.findChild('.basemap-overlay-buttons');
|
|
12987
|
+
var container = gui.container.findChild('.basemap-container');
|
|
12988
|
+
var basemapBtn = gui.container.findChild('.basemap-btn');
|
|
12989
|
+
var basemapNote = gui.container.findChild('.basemap-note');
|
|
12990
|
+
var basemapWarning = gui.container.findChild('.basemap-warning');
|
|
12991
|
+
var mapEl = gui.container.findChild('.basemap');
|
|
12992
|
+
var extentNote = El('div').addClass('basemap-prompt').appendTo(container).hide();
|
|
12993
|
+
var params = window.mapboxParams;
|
|
12994
|
+
var map;
|
|
12995
|
+
var activeStyle;
|
|
12996
|
+
var loading = false;
|
|
12997
|
+
var faded = false;
|
|
12998
|
+
|
|
12999
|
+
if (params) {
|
|
13000
|
+
// TODO: check page URL for compatibility with mapbox key
|
|
13001
|
+
init();
|
|
13002
|
+
} else {
|
|
13003
|
+
basemapBtn.hide();
|
|
13004
|
+
}
|
|
13005
|
+
|
|
13006
|
+
function init() {
|
|
13007
|
+
gui.addMode('basemap', turnOn, turnOff, basemapBtn);
|
|
13008
|
+
|
|
13009
|
+
closeBtn.on('click', function() {
|
|
13010
|
+
gui.clearMode();
|
|
13011
|
+
turnOff();
|
|
13012
|
+
});
|
|
13013
|
+
|
|
13014
|
+
clearBtn.on('click', function() {
|
|
13015
|
+
if (activeStyle) {
|
|
13016
|
+
turnOffBasemap();
|
|
13017
|
+
updateButtons();
|
|
13018
|
+
closeMenu();
|
|
13019
|
+
}
|
|
13020
|
+
});
|
|
13021
|
+
|
|
13022
|
+
fadeBtn.on('click', function() {
|
|
13023
|
+
if (faded) {
|
|
13024
|
+
mapEl.css('opacity', 1);
|
|
13025
|
+
faded = false;
|
|
13026
|
+
fadeBtn.text('Fade');
|
|
13027
|
+
} else if (activeStyle) {
|
|
13028
|
+
mapEl.css('opacity', 0.35);
|
|
13029
|
+
faded = true;
|
|
13030
|
+
fadeBtn.text('Unfade');
|
|
13031
|
+
}
|
|
13032
|
+
});
|
|
13033
|
+
|
|
13034
|
+
gui.model.on('update', onUpdate);
|
|
13035
|
+
|
|
13036
|
+
gui.on('map_click', function() {
|
|
13037
|
+
// close menu if user click on the map
|
|
13038
|
+
if (gui.getMode() == 'basemap') gui.clearMode();
|
|
13039
|
+
});
|
|
13040
|
+
|
|
13041
|
+
params.styles.forEach(function(style) {
|
|
13042
|
+
El('div')
|
|
13043
|
+
.html(`<div class="basemap-style-btn"><img src="${style.icon}"></img></div><div class="basemap-style-label">${style.name}</div>`)
|
|
13044
|
+
.appendTo(menuButtons)
|
|
13045
|
+
.findChild('.basemap-style-btn').on('click', onClick);
|
|
13046
|
+
|
|
13047
|
+
El('div').addClass('basemap-overlay-btn basemap-style-btn')
|
|
13048
|
+
.html(`<img src="${style.icon}"></img>`).on('click', onClick)
|
|
13049
|
+
.appendTo(overlayButtons);
|
|
13050
|
+
|
|
13051
|
+
function onClick() {
|
|
13052
|
+
if (overlayButtons.hasClass('disabled')) return;
|
|
13053
|
+
if (style == activeStyle) {
|
|
13054
|
+
turnOffBasemap();
|
|
13055
|
+
} else {
|
|
13056
|
+
showBasemap(style);
|
|
13057
|
+
}
|
|
13058
|
+
updateButtons();
|
|
13059
|
+
closeMenu();
|
|
13060
|
+
}
|
|
13061
|
+
});
|
|
13062
|
+
}
|
|
13063
|
+
|
|
13064
|
+
// close and turn off mode
|
|
13065
|
+
function closeMenu() {
|
|
13066
|
+
setTimeout(function() {
|
|
13067
|
+
gui.clearMode();
|
|
13068
|
+
}, 200);
|
|
13069
|
+
}
|
|
13070
|
+
|
|
13071
|
+
function turnOffBasemap() {
|
|
13072
|
+
activeStyle = null;
|
|
13073
|
+
gui.map.setDisplayCRS(null);
|
|
13074
|
+
refresh();
|
|
13075
|
+
}
|
|
13076
|
+
|
|
13077
|
+
function showBasemap(style) {
|
|
13078
|
+
activeStyle = style;
|
|
13079
|
+
// TODO: consider enabling dark basemap mode
|
|
13080
|
+
// Make sure that the selected layer style gets updated in gui-map.js
|
|
13081
|
+
// gui.state.dark_basemap = style && style.dark || false;
|
|
13082
|
+
if (map) {
|
|
13083
|
+
map.setStyle(style.url);
|
|
13084
|
+
refresh();
|
|
13085
|
+
} else if (prepareMapView()) {
|
|
13086
|
+
initMap();
|
|
13087
|
+
}
|
|
13088
|
+
}
|
|
13089
|
+
|
|
13090
|
+
function updateButtons() {
|
|
13091
|
+
menuButtons.findChildren('.basemap-style-btn').forEach(function(el, i) {
|
|
13092
|
+
el.classed('active', params.styles[i] == activeStyle);
|
|
13093
|
+
});
|
|
13094
|
+
overlayButtons.findChildren('.basemap-style-btn').forEach(function(el, i) {
|
|
13095
|
+
el.classed('active', params.styles[i] == activeStyle);
|
|
13096
|
+
});
|
|
13097
|
+
}
|
|
13098
|
+
|
|
13099
|
+
function turnOn() {
|
|
13100
|
+
onUpdate();
|
|
13101
|
+
menu.show();
|
|
13102
|
+
}
|
|
13103
|
+
|
|
13104
|
+
function onUpdate() {
|
|
13105
|
+
var activeLyr = gui.model.getActiveLayer(); // may be null
|
|
13106
|
+
var info = getDatasetCrsInfo(activeLyr?.dataset); // defaults to wgs84
|
|
13107
|
+
var dataCRS = info.crs || null;
|
|
13108
|
+
var displayCRS = gui.map.getDisplayCRS();
|
|
13109
|
+
var warning, note;
|
|
13110
|
+
|
|
13111
|
+
|
|
13112
|
+
if (!dataCRS || !displayCRS || !crsIsUsable(displayCRS) || !crsIsUsable(dataCRS)) {
|
|
13113
|
+
warning = 'This data is incompatible with the basemaps.';
|
|
13114
|
+
if (!internal.layerHasGeometry(activeLyr.layer)) {
|
|
13115
|
+
warning += ' Reason: layer is missing geographic data';
|
|
13116
|
+
} else if (!dataCRS) {
|
|
13117
|
+
warning += ' Reason: unknown projection.';
|
|
13118
|
+
}
|
|
13119
|
+
basemapWarning.html(warning).show();
|
|
13120
|
+
basemapNote.hide();
|
|
13121
|
+
overlayButtons.addClass('disabled');
|
|
13122
|
+
activeStyle = null;
|
|
13123
|
+
updateButtons();
|
|
13124
|
+
} else {
|
|
13125
|
+
note = `Your data ${activeStyle ? 'is' : 'will be'} displayed using the Mercator projection.`;
|
|
13126
|
+
basemapNote.text(note).show();
|
|
13127
|
+
overlayButtons.show();
|
|
13128
|
+
overlayButtons.removeClass('disabled');
|
|
13129
|
+
}
|
|
13130
|
+
}
|
|
13131
|
+
|
|
13132
|
+
function turnOff() {
|
|
13133
|
+
basemapWarning.hide();
|
|
13134
|
+
basemapNote.hide();
|
|
13135
|
+
menu.hide();
|
|
13136
|
+
}
|
|
13137
|
+
|
|
13138
|
+
function enabled() {
|
|
13139
|
+
return !!(mapEl && params);
|
|
13140
|
+
}
|
|
13141
|
+
|
|
13142
|
+
function show() {
|
|
13143
|
+
gui.container.addClass('basemap-on');
|
|
13144
|
+
mapEl.node().style.display = 'block';
|
|
13145
|
+
}
|
|
13146
|
+
|
|
13147
|
+
function hide() {
|
|
13148
|
+
gui.container.removeClass('basemap-on');
|
|
13149
|
+
mapEl.node().style.display = 'none';
|
|
13150
|
+
}
|
|
13151
|
+
|
|
13152
|
+
function getLonLatBounds() {
|
|
13153
|
+
var ext = gui.map.getExtent();
|
|
13154
|
+
var bbox = ext.getBounds().toArray();
|
|
13155
|
+
var bbox2 = fromWebMercator(bbox[0], bbox[1])
|
|
13156
|
+
.concat(fromWebMercator(bbox[2], bbox[3]));
|
|
13157
|
+
return bbox2;
|
|
13158
|
+
}
|
|
13159
|
+
|
|
13160
|
+
function initMap() {
|
|
13161
|
+
if (!enabled() || map || loading) return;
|
|
13162
|
+
loading = true;
|
|
13163
|
+
loadStylesheet(params.css);
|
|
13164
|
+
loadScript(params.js, function() {
|
|
13165
|
+
map = new window.mapboxgl.Map({
|
|
13166
|
+
accessToken: params.key,
|
|
13167
|
+
logoPosition: 'bottom-left',
|
|
13168
|
+
container: mapEl.node(),
|
|
13169
|
+
style: activeStyle.url,
|
|
13170
|
+
bounds: getLonLatBounds(),
|
|
13171
|
+
doubleClickZoom: false,
|
|
13172
|
+
dragPan: false,
|
|
13173
|
+
dragRotate: false,
|
|
13174
|
+
scrollZoom: false,
|
|
13175
|
+
interactive: false,
|
|
13176
|
+
keyboard: false,
|
|
13177
|
+
maxPitch: 0,
|
|
13178
|
+
renderWorldCopies: true // false // false prevents panning off the map
|
|
13179
|
+
});
|
|
13180
|
+
map.on('load', function() {
|
|
13181
|
+
loading = false;
|
|
13182
|
+
refresh();
|
|
13183
|
+
});
|
|
13184
|
+
});
|
|
13185
|
+
}
|
|
13186
|
+
|
|
13187
|
+
// @bbox: latlon bounding box of current map extent
|
|
13188
|
+
function checkBounds(bbox) {
|
|
13189
|
+
var ext = gui.map.getExtent();
|
|
13190
|
+
var mpp = ext.getBounds().width() / ext.width();
|
|
13191
|
+
var z = scaleToZoom(mpp);
|
|
13192
|
+
var msg;
|
|
13193
|
+
if (bbox[1] >= -85 && bbox[3] <= 85 && z <= 20) {
|
|
13194
|
+
extentNote.hide();
|
|
13195
|
+
return true;
|
|
13196
|
+
}
|
|
13197
|
+
if (z > 20) {
|
|
13198
|
+
msg = 'zoom out';
|
|
13199
|
+
} else if (bbox[1] > 0) {
|
|
13200
|
+
msg = 'pan south';
|
|
13201
|
+
} else if (bbox[3] < 0) {
|
|
13202
|
+
msg = 'pan north';
|
|
13203
|
+
} else {
|
|
13204
|
+
msg = msg = 'zoom in';
|
|
13205
|
+
}
|
|
13206
|
+
extentNote.html(msg + ' to see the basemap').show();
|
|
13207
|
+
return false;
|
|
13208
|
+
}
|
|
13209
|
+
|
|
13210
|
+
function crsIsUsable(crs) {
|
|
13211
|
+
if (!crs) return false;
|
|
13212
|
+
if (!internal.isInvertibleCRS(crs)) return false;
|
|
13213
|
+
return true;
|
|
13214
|
+
}
|
|
13215
|
+
|
|
13216
|
+
function prepareMapView() {
|
|
13217
|
+
var crs = gui.map.getDisplayCRS();
|
|
13218
|
+
if (!crs) return false;
|
|
13219
|
+
if (!internal.isWebMercator(crs)) {
|
|
13220
|
+
gui.map.setDisplayCRS(internal.parseCrsString('webmercator'));
|
|
13221
|
+
}
|
|
13222
|
+
return true;
|
|
13223
|
+
}
|
|
13224
|
+
|
|
13225
|
+
function refresh() {
|
|
13226
|
+
var crs = gui.map.getDisplayCRS();
|
|
13227
|
+
var off = !crs || !enabled() || !map || loading || !activeStyle;
|
|
13228
|
+
fadeBtn.active(!off);
|
|
13229
|
+
clearBtn.active(!off);
|
|
13230
|
+
if (off) {
|
|
13231
|
+
hide();
|
|
13232
|
+
extentNote.hide();
|
|
13233
|
+
return;
|
|
13234
|
+
}
|
|
13235
|
+
|
|
13236
|
+
prepareMapView();
|
|
13237
|
+
var bbox = getLonLatBounds();
|
|
13238
|
+
if (!checkBounds(bbox)) {
|
|
13239
|
+
// map does not display outside these bounds
|
|
13240
|
+
hide();
|
|
13241
|
+
} else {
|
|
13242
|
+
show();
|
|
13243
|
+
map.resize();
|
|
13244
|
+
map.fitBounds(bbox, {animate: false});
|
|
13245
|
+
}
|
|
13246
|
+
}
|
|
13247
|
+
|
|
13248
|
+
return {refresh, show: onUpdate};
|
|
13249
|
+
}
|
|
13250
|
+
|
|
13209
13251
|
function GuiInstance(container, opts) {
|
|
13210
13252
|
var gui = new ModeSwitcher();
|
|
13211
13253
|
opts = utils$1.extend({
|
|
@@ -13223,6 +13265,7 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13223
13265
|
gui.model = new Model(gui);
|
|
13224
13266
|
gui.keyboard = new KeyboardEvents(gui);
|
|
13225
13267
|
gui.buttons = new SidebarButtons(gui);
|
|
13268
|
+
gui.basemap = new Basemap(gui);
|
|
13226
13269
|
gui.session = new SessionHistory(gui);
|
|
13227
13270
|
gui.contextMenu = new ContextMenu();
|
|
13228
13271
|
gui.undo = new Undo(gui);
|
|
@@ -13388,6 +13431,7 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13388
13431
|
if (dataLoaded) return;
|
|
13389
13432
|
dataLoaded = true;
|
|
13390
13433
|
gui.buttons.show();
|
|
13434
|
+
gui.basemap.show();
|
|
13391
13435
|
El('#mode-buttons').show();
|
|
13392
13436
|
El('#splash-buttons').hide();
|
|
13393
13437
|
El('body').addClass('map-view');
|
package/www/mapshaper.js
CHANGED
|
@@ -38860,14 +38860,15 @@ ${svg}
|
|
|
38860
38860
|
return mergeDatasetsIntoDataset(target.dataset, datasets);
|
|
38861
38861
|
};
|
|
38862
38862
|
|
|
38863
|
-
cmd.rectangle = function(
|
|
38863
|
+
cmd.rectangle = function(target, opts) {
|
|
38864
38864
|
var bounds, crsInfo;
|
|
38865
|
-
if (
|
|
38866
|
-
bounds = getLayerBounds(source.layer, source.dataset.arcs);
|
|
38867
|
-
crsInfo = getDatasetCrsInfo(source.dataset);
|
|
38868
|
-
} else if (opts.bbox) {
|
|
38865
|
+
if (opts.bbox) {
|
|
38869
38866
|
bounds = new Bounds(opts.bbox);
|
|
38870
|
-
crsInfo =
|
|
38867
|
+
crsInfo = target && getDatasetCrsInfo(target.dataset) ||
|
|
38868
|
+
probablyDecimalDegreeBounds(bounds) && getCrsInfo('wgs84') || {};
|
|
38869
|
+
} else if (target) {
|
|
38870
|
+
bounds = getLayerBounds(target.layer, target.dataset.arcs);
|
|
38871
|
+
crsInfo = getDatasetCrsInfo(target.dataset);
|
|
38871
38872
|
}
|
|
38872
38873
|
bounds = bounds && applyRectangleOptions(bounds, crsInfo.crs, opts);
|
|
38873
38874
|
if (!bounds || !bounds.hasBounds()) {
|
|
@@ -45371,7 +45372,7 @@ ${svg}
|
|
|
45371
45372
|
stop('Command requires a width= argument');
|
|
45372
45373
|
}
|
|
45373
45374
|
if (source || opts.bbox || targets.length === 0) {
|
|
45374
|
-
job.catalog.addDataset(cmd.rectangle(source, opts));
|
|
45375
|
+
job.catalog.addDataset(cmd.rectangle(source || targets?.[0], opts));
|
|
45375
45376
|
} else {
|
|
45376
45377
|
outputLayers = cmd.rectangle2(targets[0], opts);
|
|
45377
45378
|
}
|
|
@@ -45535,7 +45536,7 @@ ${svg}
|
|
|
45535
45536
|
});
|
|
45536
45537
|
}
|
|
45537
45538
|
|
|
45538
|
-
var version = "0.6.
|
|
45539
|
+
var version = "0.6.83";
|
|
45539
45540
|
|
|
45540
45541
|
// Parse command line args into commands and run them
|
|
45541
45542
|
// Function takes an optional Node-style callback. A Promise is returned if no callback is given.
|
package/www/page.css
CHANGED
|
@@ -1124,8 +1124,6 @@ img.close-btn:hover,
|
|
|
1124
1124
|
height: 100%;
|
|
1125
1125
|
}
|
|
1126
1126
|
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
1127
|
.basemap-styles {
|
|
1130
1128
|
margin: 0 -2px;
|
|
1131
1129
|
white-space: nowrap;
|
|
@@ -1155,26 +1153,63 @@ img.close-btn:hover,
|
|
|
1155
1153
|
margin-left: 10px;
|
|
1156
1154
|
}
|
|
1157
1155
|
|
|
1156
|
+
.basemap-style-btn {
|
|
1157
|
+
position: relative;
|
|
1158
|
+
border-width: 2px;
|
|
1159
|
+
border-color: #98cde2;
|
|
1160
|
+
border-color: #bbddea;
|
|
1161
|
+
border-style: solid;
|
|
1162
|
+
border-radius: 6px;
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1158
1165
|
.basemap-style-btn img {
|
|
1159
1166
|
display: block;
|
|
1160
|
-
position: relative;
|
|
1161
|
-
border: 2px solid transparent;
|
|
1162
1167
|
width: 108px;
|
|
1163
1168
|
}
|
|
1164
1169
|
|
|
1165
|
-
div.basemap-style-btn.active
|
|
1166
|
-
border:
|
|
1170
|
+
div.basemap-style-btn.active {
|
|
1171
|
+
border-color: #e8ba52;
|
|
1167
1172
|
}
|
|
1168
1173
|
|
|
1169
|
-
.basemap-style-btn:hover
|
|
1174
|
+
.basemap-buttons:not(.disabled) .basemap-style-btn:hover {
|
|
1170
1175
|
cursor: pointer;
|
|
1171
|
-
border:
|
|
1176
|
+
border-color: #f7e286;
|
|
1172
1177
|
}
|
|
1173
1178
|
|
|
1174
1179
|
.basemap-style-label {
|
|
1175
1180
|
margin-left: 2px;
|
|
1176
1181
|
}
|
|
1177
1182
|
|
|
1183
|
+
.basemap-overlay-buttons {
|
|
1184
|
+
z-index: 20;
|
|
1185
|
+
position: absolute;
|
|
1186
|
+
top: 6px;
|
|
1187
|
+
right: 36px;
|
|
1188
|
+
padding: 4px;
|
|
1189
|
+
background: white;
|
|
1190
|
+
border-radius: 7px;
|
|
1191
|
+
line-height: 0px;
|
|
1192
|
+
display: none;
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
.basemap-style-btn.basemap-overlay-btn {
|
|
1196
|
+
width: 35px;
|
|
1197
|
+
height: 35px;
|
|
1198
|
+
margin: 3px;
|
|
1199
|
+
overflow: hidden;
|
|
1200
|
+
display: inline-block;
|
|
1201
|
+
/*border-width: 1px;*/
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
.basemap-overlay-buttons.disabled > div {
|
|
1205
|
+
opacity: 0.5;
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
.basemap-overlay-btn img {
|
|
1209
|
+
margin-left: -21px;
|
|
1210
|
+
width: 70px;
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1178
1213
|
.mapbox-improve-map {
|
|
1179
1214
|
display: none;
|
|
1180
1215
|
}
|
|
@@ -1254,10 +1289,11 @@ body.pan.panning .map-layers:not(.drawing) {
|
|
|
1254
1289
|
z-index: 20;
|
|
1255
1290
|
position: absolute;
|
|
1256
1291
|
text-align: center;
|
|
1257
|
-
top:
|
|
1292
|
+
top: 6px;
|
|
1258
1293
|
right: 0;
|
|
1259
1294
|
padding: 3px;
|
|
1260
1295
|
background-color: rgba(255, 255, 255, 1);
|
|
1296
|
+
border-radius: 7px;
|
|
1261
1297
|
}
|
|
1262
1298
|
|
|
1263
1299
|
.nav-btn-wrapper {
|
|
@@ -1327,6 +1363,7 @@ body.pan.panning .map-layers:not(.drawing) {
|
|
|
1327
1363
|
|
|
1328
1364
|
.nav-btn.selected {
|
|
1329
1365
|
background-color: black;
|
|
1366
|
+
border-radius: 5px;
|
|
1330
1367
|
}
|
|
1331
1368
|
|
|
1332
1369
|
.nav-btn:hover:not(.disabled) svg *,
|