From 0a2049563884a504113af59a094042bbf4c75d6d Mon Sep 17 00:00:00 2001
From: Matthew Bloch
Date: Mon, 1 Apr 2024 15:52:09 -0400
Subject: [PATCH] Update website
---
mapshaper-gui.js | 214 +++++++++++++++++++++++++++++++++--------------
mapshaper.js | 3 +-
2 files changed, 152 insertions(+), 65 deletions(-)
diff --git a/mapshaper-gui.js b/mapshaper-gui.js
index 47382f5a..c588825d 100644
--- a/mapshaper-gui.js
+++ b/mapshaper-gui.js
@@ -2778,30 +2778,7 @@
function getDefaultStyle(lyr, baseStyle) {
- var style = Object.assign({}, baseStyle);
- // reduce the dot size of large point layers
- if (lyr.geometry_type == 'point' && style.dotSize > 0) {
- style.dotSize *= getDotScale$1(lyr);
- }
- return style;
- }
-
- function getDotScale$1(lyr) {
- var topTier = 10000;
- var n = countPoints(lyr.shapes, topTier); // short-circuit point counting above top threshold
- var k = n < 200 && 4 || n < 2500 && 3 || n < topTier && 2 || 1;
- return k;
- }
-
- function countPoints(shapes, max) {
- var count = 0;
- var i, n, shp;
- max = max || Infinity;
- for (i=0, n=shapes.length; i bbox[0] && p[0] < bbox[2] && p[1] > bbox[1] && p[1] < bbox[3];
+ };
+ var topTier = 50000;
+ var count = 0;
+ layers = layers.filter(function(lyr) {
+ return lyr.geometry_type == 'point' && lyr.gui.style.dotSize > 0;
+ });
+ layers.forEach(function(lyr) {
+ // short-circuit point counting above top threshold
+ count += countPoints(lyr.gui.displayLayer.shapes, topTier, testInBounds);
+ });
+ count = Math.min(topTier, count) || 1;
+ var k = Math.pow(6 - utils$1.clamp(Math.log10(count), 1, 5), 1.3);
+
+ // zoom adjustments
+ var mapScale = ext.scale();
+ if (mapScale < 0.5) {
+ k *= Math.pow(mapScale + 0.5, 0.35);
+ } else if (mapScale > 1) {
+ // scale faster at first
+ k *= Math.pow(Math.min(mapScale, 4), 0.15);
+ k *= Math.pow(mapScale, 0.05);
+ }
+
+ // scale down when map is small
+ var smallSide = Math.min(ext.width(), ext.height());
+ k *= utils$1.clamp(smallSide / 500, 0.5, 1);
+
+ layers.forEach(function(lyr) {
+ lyr.gui.style.dotScale = k;
+ });
+ if (overlayLyr && overlayLyr.geometry_type == 'point' && overlayLyr.gui.style.dotSize > 0) {
+ overlayLyr.gui.style.dotScale = k;
+ }
+ }
+
+ function countPoints(shapes, max, filter) {
+ var count = 0;
+ var i, j, n, m, shp;
+ for (i=0, n=shapes.length; i 1.5) return false;
+ }
+ return true;
+ }
+
function setZ(lyr, z) {
lyr.gui.source.dataset.arcs.setRetainedInterval(z);
if (isProjectedLayer(lyr)) {
@@ -5755,29 +5802,37 @@
var self = this;
var shiftDown = false;
var ctrlDown = false;
+ var metaDown = false;
+ var altDown = false;
+
+ function updateControlKeys(e) {
+ shiftDown = e.shiftKey;
+ ctrlDown = e.ctrlKey;
+ metaDown = e.metaKey;
+ altDown = e.altKey;
+ }
document.addEventListener('keyup', function(e) {
if (!GUI.isActiveInstance(gui)) return;
// this can fail to fire if keyup occurs over a context menu
- shiftDown = e.shiftKey;
- ctrlDown = e.ctrlKey;
+ updateControlKeys(e);
self.dispatchEvent('keyup', getEventData(e));
});
document.addEventListener('keydown', function(e) {
if (!GUI.isActiveInstance(gui)) return;
- shiftDown = e.shiftKey;
- ctrlDown = e.ctrlKey;
+ updateControlKeys(e);
self.dispatchEvent('keydown', getEventData(e));
});
document.addEventListener('mousemove', function(e) {
// refreshing these here to prevent problems when context menu opens
- shiftDown = e.shiftKey;
- ctrlDown = e.ctrlKey;
+ updateControlKeys(e);
});
this.shiftIsPressed = function() { return shiftDown; };
this.ctrlIsPressed = function() { return ctrlDown; };
+ this.altIsPressed = function() { return altDown; };
+ this.metaIsPressed = function() { return metaDown; };
this.onMenuSubmit = function(menuEl, cb) {
gui.on('enter_key', function(e) {
@@ -9317,8 +9372,7 @@
function useBoxZoom() {
var mode = gui.getMode();
- var disabled = ['selection_tool', 'box_tool', 'rectangle_tool'].includes(mode);
- return !disabled;
+ return !'selection_tool,box_tool,rectangle_tool,drawing_tool'.includes(mode);
}
function getBoxData(e) {
@@ -10278,6 +10332,7 @@
var drawingId = -1; // feature id of path being drawn
var sessionCount = 0;
var alert;
+ var pencilPoints;
var _dragging = false;
function active() {
@@ -10292,6 +10347,10 @@
return drawingId > -1;
}
+ function usingPencil() {
+ return (gui.keyboard.altIsPressed() || gui.keyboard.metaIsPressed()) && active() && !dragging();
+ }
+
function polygonMode() {
return active() && hit.getHitTarget().geometry_type == 'polygon';
}
@@ -10373,11 +10432,12 @@
function showInstructions() {
var isMac = navigator.userAgent.includes('Mac');
- var symbol = isMac ? '⌘' : '^';
+ var undoKey = isMac ? '⌘' : '^';
+ var drawKey = isMac ? '⌘' : 'Alt';
var pathStr = polygonMode() ? 'closed paths' : 'paths';
- var msg = `Instructions: Click on the map to draw ${pathStr}. Drag vertices to reshape a path. Type ${symbol}Z/${symbol}Y to undo/redo.`;
+ var msg = `Instructions: Click to start a path or add a point. ${drawKey}-drag draws a path. Drag points to reshape. Type ${undoKey}Z/${undoKey}Y to undo/redo.`;
alert = showPopupAlert(msg, null, {
- non_blocking: true, max_width: '360px'});
+ non_blocking: true, max_width: '388px'});
}
function hideInstructions() {
@@ -10462,9 +10522,28 @@
hit.setHoverVertex(hoverVertexInfo.displayPoint, hoverVertexInfo.type);
});
+ gui.map.getMouse().on('drag', function(e) {
+ if (!usingPencil()) return;
+ e.stopPropagation();
+ var xy = [e.x, e.y];
+ var p = pixToDataCoords(e.x, e.y);
+ if (!drawing()) {
+ pencilPoints = [xy];
+ startNewPath(p);
+ } else if (!pencilPoints || !pencilPointIsSkippable(xy, pencilPoints)) {
+ pencilPoints = [xy];
+ extendCurrentPath(p);
+ } else {
+ // skip this point, update the hover line
+ pencilPoints.push(xy);
+ updatePathEndpoint(p);
+ }
+ }, null, 3); // higher priority than hit control
+
hit.on('drag', function(e) {
if (!dragging() || drawing()) return;
e.originalEvent.stopPropagation();
+ // dragging a vertex
var target = hit.getHitTarget();
var p = ext.translatePixelCoords(e.x, e.y);
if (gui.keyboard.shiftIsPressed()) {
@@ -10543,8 +10622,6 @@
deleteActiveVertex(e);
} else {
startNewPath(p);
- hideInstructions();
- updateCursor();
}
prevClickEvent = e;
});
@@ -10655,6 +10732,14 @@
gui.dispatchEvent('path_add', {target, p1, p2});
drawingId = target.shapes.length - 1;
hit.setDrawingId(drawingId);
+ hideInstructions();
+ updateCursor();
+ }
+
+ function pencilDraw(e) {
+ var p = pixToDataCoords(e.x, e.y);
+ extendCurrentPath(p);
+
}
// p: [x, y] source data coordinates of new point on path
@@ -11442,8 +11527,7 @@
_self.drawSquareDots = function(shapes, style) {
var t = getScaledTransform(_ext),
- scaleRatio = getDotScale(_ext),
- size = Math.round((style.dotSize || 1) * scaleRatio),
+ size = getDotSize(style),
styler = style.styler || null,
xmax = _canvas.width + size,
ymax = _canvas.height + size,
@@ -11463,7 +11547,7 @@
for (i=0, n=shapes.length; i 1) {
- // scale faster at first, so small dots in large datasets
- // become easily visible and clickable after zooming in a bit
- k *= Math.pow(Math.min(mapScale, 10), 0.3);
- k *= Math.pow(mapScale, 0.1);
- }
- // grow pixels more slowly on retina displays (to reduce number of pixels to
- // draw for large point datasets when slightly zoomed in)
- var l = Math.pow(GUI.getPixelRatio(), 0.8);
- return j * k * l;
+ function getDotSize(style) {
+ var size = style.dotSize || 1;
+ // TODO: improve
+ var scale = style.dotScale || 1;
+ size += (scale - 1) / 2;
+ size *= Math.pow(scale, 0.3);
+
+ // shrink dots slightly on retina displays, to adjust for greater clarity
+ // and reduce number of pixels to draw on large datasets.
+ return Math.round(Math.pow(GUI.getPixelRatio(), 0.8) * size);
}
function getScaledTransform(ext) {
@@ -12698,10 +12773,7 @@ GUI and setting the size and crop of SVG output.