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>
<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>
<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
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
// as the grid becomes more crammed.
// There are 4 levels from 0 to 3.
@ -221,6 +227,10 @@ function addBiome(biomeDef) {
lastBiomeID++;
}
// Current cursor position on the canvas
let canvas_cursor_x = null;
let canvas_cursor_y = null;
// 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})
@ -919,6 +929,27 @@ function draw(recalculate) {
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;
}
@ -1096,6 +1127,15 @@ function getNearestPointFromCanvasPos(x, y, maxDist) {
// Whether the mouse is currently pressed
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
// or is about to start
let dragDropStartPos = null;
@ -1149,6 +1189,10 @@ function updateAltitudeText() {
/* Update the text that shows the biome coordinates
of the cursor when it's on the diagram */
function updateCoordinateDisplay(pixelX, pixelY) {
if (pixelX === null || pixelY === null) {
coordinateDisplay.innerHtml = "&nbsp;";
return;
}
// show coordinates
let [heat, humidity] = canvasPixelCoordsToBiomeCoords(pixelX, pixelY);
if (!drawError) {
@ -1162,21 +1206,27 @@ function updateCoordinateDisplay(pixelX, pixelY) {
/* Updates and changes the cursor type on the diagram
canvas depending on whether we can select, drag or do nothing
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) {
// a special message is shown; use auto cursor
voronoiCanvas.style.cursor = "auto";
return
}
let nearest = getNearestPointFromCanvasPos(event.offsetX, event.offsetY, POINT_SELECT_DISTANCE);
let nearest = getNearestPointFromCanvasPos(x, y, POINT_SELECT_DISTANCE);
if (nearest !== null) {
let [id, elem] = getSelectedBiomeIDAndElement();
if (id !== null && nearest.id === id) {
// This cursor indicates we can grab the point
voronoiCanvas.style.cursor = "grab";
} else {
// This cursor indicates we can grab the point
// This cursor indicates we can select the point
voronoiCanvas.style.cursor = "crosshair";
}
} else {
@ -1237,9 +1287,58 @@ function initBiomeColorSelectors() {
/***** 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) {
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
if (dragDropState !== 2 && dragDropPointID !== null && mouseIsDown && dragDropStartPos !== null) {
let dist = getDistance(dragDropStartPos.x, dragDropStartPos.y, event.offsetX, event.offsetY)
@ -1254,17 +1353,34 @@ voronoiCanvas.onmousemove = function(event) {
updatePointWhenDragged(dragDropPointID);
}
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) {
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) {
// select point by clicking.
// initiate drag-n-drop if already selected.
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) {
// Points need to be shown for drag-n-drop to work
return;
@ -1281,7 +1397,7 @@ voronoiCanvas.onmousedown = function(event) {
if (alreadySelected) {
dragDropState = 1;
}
updateDragDropCursorStatus();
updateCanvasCursorStatus(event.offsetX, event.offsetY);
}
}
voronoiCanvas.onmouseup = function(event) {
@ -1300,7 +1416,10 @@ voronoiCanvas.onmouseleave = function() {
dragDropStartPos = null;
dragDropPointID = null;
dragDropState = 0;
canvas_cursor_x = null;
canvas_cursor_y = null;
coordinateDisplay.innerHTML = "&nbsp;";
draw(false);
}
/* Biome list events */