Allow resizing of canvas

This commit is contained in:
Wuzzy 2023-10-24 23:17:22 +02:00
parent 0e79b5d09d
commit f5ae56cc9c
2 changed files with 128 additions and 7 deletions

View File

@ -45,6 +45,8 @@
<h3>Diagram</h3> <h3>Diagram</h3>
<p>Hover with the mouse cursor over the diagram to see the heat and humidity coordinates at this position. You can click on a dot to select it, click on it again and hold down the mouse button to drag it.</p> <p>Hover with the mouse cursor over the diagram to see the heat and humidity coordinates at this position. You can click on a dot to select it, click on it again and hold down the mouse button to drag it.</p>
<p>When you hover the diagram, a small grabbing widget will apper in the bottom left corner. You can use this to resize the whole diagram. Hold down Shift while resizing to preserve the aspect ratio.</p>
<h3>Biome configuration</h3> <h3>Biome configuration</h3>
<p>Here you can see a list of all currently active biomes. Each biome has a name of your choice. The program always starts with a default biome at (50, 50). Select a biome in the list so you can edit it.</p> <p>Here you can see a list of all currently active biomes. Each biome has a name of your choice. The program always starts with a default biome at (50, 50). Select a biome in the list so you can edit it.</p>

133
mibpov.js
View File

@ -7,6 +7,12 @@ const MAX_Y_DEFAULT = 31000
// Draw a grid line every GRID_STEP units // Draw a grid line every GRID_STEP units
const GRID_STEP = 10 const GRID_STEP = 10
// Size of the resizing corner
const RESIZE_CORNER = 18;
// Minimum canvas side length (px)
const MIN_CANVAS_SIZE = 100;
// Grid widths. We use lower grid widths // Grid widths. We use lower grid widths
// as the grid becomes more crammed. // as the grid becomes more crammed.
// There are 4 levels from 0 to 3. // There are 4 levels from 0 to 3.
@ -221,6 +227,10 @@ function addBiome(biomeDef) {
lastBiomeID++; lastBiomeID++;
} }
// Current cursor position on the canvas
let canvas_cursor_x = null;
let canvas_cursor_y = null;
// Add a default biome at the midpoint // Add a default biome at the midpoint
addBiome({name: "default", heat:midpoint_heat, humidity:midpoint_humidity, min_y: MIN_Y_DEFAULT, max_y: MAX_Y_DEFAULT}) addBiome({name: "default", heat:midpoint_heat, humidity:midpoint_humidity, min_y: MIN_Y_DEFAULT, max_y: MAX_Y_DEFAULT})
@ -919,6 +929,27 @@ function draw(recalculate) {
putPointName(context, point); putPointName(context, point);
} }
} }
if (canvas_cursor_x !== null) {
const RESIZE_CORNER = 14;
context.beginPath();
context.moveTo(voronoiCanvas.width, voronoiCanvas.height - RESIZE_CORNER);
context.lineTo(voronoiCanvas.width - RESIZE_CORNER, voronoiCanvas.height);
context.lineTo(voronoiCanvas.width, voronoiCanvas.height);
context.fillStyle = "#80808080";
context.closePath();
context.fill();
context.beginPath();
context.lineWidth = 1;
for (let c = RESIZE_CORNER; c>0; c-=4) {
context.moveTo(voronoiCanvas.width, voronoiCanvas.height - c);
context.lineTo(voronoiCanvas.width - c, voronoiCanvas.height);
}
context.strokeStyle = "#00000080";
context.closePath();
context.stroke();
}
return true; return true;
} }
@ -1096,6 +1127,15 @@ function getNearestPointFromCanvasPos(x, y, maxDist) {
// Whether the mouse is currently pressed // Whether the mouse is currently pressed
let mouseIsDown = false; let mouseIsDown = false;
// Whether the canvas is being resized
let resizing = false;
// Start coordinates of canvas resize or null if not resizing
let resizing_start_pos_x = null;
let resizing_start_pos_y = null;
// Start size of canvas when resizing or null if not resizing
let resizing_start_size_x = null;
let resizing_start_size_y = null;
// Coordinates of where the drag-n-drop started // Coordinates of where the drag-n-drop started
// or is about to start // or is about to start
let dragDropStartPos = null; let dragDropStartPos = null;
@ -1149,6 +1189,10 @@ function updateAltitudeText() {
/* Update the text that shows the biome coordinates /* Update the text that shows the biome coordinates
of the cursor when it's on the diagram */ of the cursor when it's on the diagram */
function updateCoordinateDisplay(pixelX, pixelY) { function updateCoordinateDisplay(pixelX, pixelY) {
if (pixelX === null || pixelY === null) {
coordinateDisplay.innerHtml = "&nbsp;";
return;
}
// show coordinates // show coordinates
let [heat, humidity] = canvasPixelCoordsToBiomeCoords(pixelX, pixelY); let [heat, humidity] = canvasPixelCoordsToBiomeCoords(pixelX, pixelY);
if (!drawError) { if (!drawError) {
@ -1162,21 +1206,27 @@ function updateCoordinateDisplay(pixelX, pixelY) {
/* Updates and changes the cursor type on the diagram /* Updates and changes the cursor type on the diagram
canvas depending on whether we can select, drag or do nothing canvas depending on whether we can select, drag or do nothing
at the pointed position */ at the pointed position */
function updateDragDropCursorStatus() { function updateCanvasCursorStatus(x, y) {
// Show resize cursor at the bottom right corner
if (resizing || (x > voronoiCanvas.width - RESIZE_CORNER && y > voronoiCanvas.height - RESIZE_CORNER)) {
voronoiCanvas.style.cursor = "nwse-resize";
return
}
if (drawError || !showPoints) { if (drawError || !showPoints) {
// a special message is shown; use auto cursor // a special message is shown; use auto cursor
voronoiCanvas.style.cursor = "auto"; voronoiCanvas.style.cursor = "auto";
return return
} }
let nearest = getNearestPointFromCanvasPos(event.offsetX, event.offsetY, POINT_SELECT_DISTANCE); let nearest = getNearestPointFromCanvasPos(x, y, POINT_SELECT_DISTANCE);
if (nearest !== null) { if (nearest !== null) {
let [id, elem] = getSelectedBiomeIDAndElement(); let [id, elem] = getSelectedBiomeIDAndElement();
if (id !== null && nearest.id === id) { if (id !== null && nearest.id === id) {
// This cursor indicates we can grab the point // This cursor indicates we can grab the point
voronoiCanvas.style.cursor = "grab"; voronoiCanvas.style.cursor = "grab";
} else { } else {
// This cursor indicates we can grab the point // This cursor indicates we can select the point
voronoiCanvas.style.cursor = "crosshair"; voronoiCanvas.style.cursor = "crosshair";
} }
} else { } else {
@ -1237,9 +1287,58 @@ function initBiomeColorSelectors() {
/***** EVENTS *****/ /***** EVENTS *****/
/* Canvas events */ /* Body events */
document.body.onmousemove = function(event) {
if (resizing) {
// Get x,y position of canvas
let bodyRect = document.body.getBoundingClientRect();
let canvasRect = voronoiCanvas.getBoundingClientRect();
let cx = canvasRect.left - bodyRect.left;
let cy = canvasRect.top - bodyRect.top;
// Calculate new size
let rx = event.pageX - resizing_start_pos_x - cx;
let ry = event.pageY - resizing_start_pos_y - cy;
// Limit the width
let maxX = (bodyRect.width - cx) - 20;
// Resize
voronoiCanvas.width = Math.min(maxX, Math.max(MIN_CANVAS_SIZE, resizing_start_size_x + rx));
// Holding down Shift preserves aspect ratio
if (event.shiftKey) {
voronoiCanvas.height = voronoiCanvas.width;
} else {
voronoiCanvas.height = Math.max(MIN_CANVAS_SIZE, resizing_start_size_y + ry);
}
draw(false);
return;
}
}
document.body.onmouseup = function(event) {
if (resizing) {
resizing = false;
updateCanvasCursorStatus(event.offsetX, event.offsetY);
}
}
document.body.onmouseleave = function(event) {
if (resizing) {
resizing = false;
updateCanvasCursorStatus(event.offsetX, event.offsetY);
}
}
/* Canvas events */
voronoiCanvas.onmousemove = function(event) { voronoiCanvas.onmousemove = function(event) {
if (resizing) {
updateCoordinateDisplay(event.offsetX, event.offsetY);
updateCanvasCursorStatus(event.offsetX, event.offsetY);
canvas_cursor_x = event.offsetX;
canvas_cursor_y = event.offsetY;
draw(false);
return
}
// update drag-n-drop state // update drag-n-drop state
if (dragDropState !== 2 && dragDropPointID !== null && mouseIsDown && dragDropStartPos !== null) { if (dragDropState !== 2 && dragDropPointID !== null && mouseIsDown && dragDropStartPos !== null) {
let dist = getDistance(dragDropStartPos.x, dragDropStartPos.y, event.offsetX, event.offsetY) let dist = getDistance(dragDropStartPos.x, dragDropStartPos.y, event.offsetX, event.offsetY)
@ -1254,17 +1353,34 @@ voronoiCanvas.onmousemove = function(event) {
updatePointWhenDragged(dragDropPointID); updatePointWhenDragged(dragDropPointID);
} }
updateCoordinateDisplay(event.offsetX, event.offsetY); updateCoordinateDisplay(event.offsetX, event.offsetY);
updateDragDropCursorStatus(); updateCanvasCursorStatus(event.offsetX, event.offsetY);
canvas_cursor_x = event.offsetX;
canvas_cursor_y = event.offsetY;
draw(false);
} }
voronoiCanvas.onmouseenter = function(event) { voronoiCanvas.onmouseenter = function(event) {
updateCoordinateDisplay(event.offsetX, event.offsetY); updateCoordinateDisplay(event.offsetX, event.offsetY);
updateDragDropCursorStatus(); updateCanvasCursorStatus(event.offsetX, event.offsetY);
canvas_cursor_x = event.offsetX;
canvas_cursor_y = event.offsetY;
draw(false);
} }
voronoiCanvas.onmousedown = function(event) { voronoiCanvas.onmousedown = function(event) {
// select point by clicking. // select point by clicking.
// initiate drag-n-drop if already selected. // initiate drag-n-drop if already selected.
mouseIsDown = true; mouseIsDown = true;
// Resizing the canvas
if (event.offsetX > voronoiCanvas.width - RESIZE_CORNER && event.offsetY > voronoiCanvas.height - RESIZE_CORNER) {
resizing_start_pos_x = event.offsetX;
resizing_start_pos_y = event.offsetY;
resizing_start_size_x = +this.width;
resizing_start_size_y = +this.height;
resizing = true;
return;
}
if (drawError || !showPoints) { if (drawError || !showPoints) {
// Points need to be shown for drag-n-drop to work // Points need to be shown for drag-n-drop to work
return; return;
@ -1281,7 +1397,7 @@ voronoiCanvas.onmousedown = function(event) {
if (alreadySelected) { if (alreadySelected) {
dragDropState = 1; dragDropState = 1;
} }
updateDragDropCursorStatus(); updateCanvasCursorStatus(event.offsetX, event.offsetY);
} }
} }
voronoiCanvas.onmouseup = function(event) { voronoiCanvas.onmouseup = function(event) {
@ -1300,7 +1416,10 @@ voronoiCanvas.onmouseleave = function() {
dragDropStartPos = null; dragDropStartPos = null;
dragDropPointID = null; dragDropPointID = null;
dragDropState = 0; dragDropState = 0;
canvas_cursor_x = null;
canvas_cursor_y = null;
coordinateDisplay.innerHTML = "&nbsp;"; coordinateDisplay.innerHTML = "&nbsp;";
draw(false);
} }
/* Biome list events */ /* Biome list events */