Add grid scaling.
This commit is contained in:
parent
0992cf97eb
commit
3f4aee73a3
1 changed files with 51 additions and 10 deletions
|
|
@ -24,6 +24,11 @@
|
|||
top: 10px;
|
||||
transform: translateX(-50%);
|
||||
z-index: 10000;
|
||||
max-width: calc(100% - 20px);
|
||||
}
|
||||
|
||||
#toolBar::-webkit-scrollbar {
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
#coords {
|
||||
|
|
@ -43,7 +48,12 @@
|
|||
<div class="container">
|
||||
<div id="grid" class="position-relative overflow-hidden">
|
||||
<div id="toolBar"
|
||||
class="btn-toolbar bg-light position-absolute border border-secondary-subtle rounded start-50 p-1">
|
||||
class="btn-toolbar bg-light position-absolute border border-secondary-subtle rounded start-50 p-1 align-items-center flex-nowrap overflow-auto">
|
||||
<div class="input-group input-group-sm w-auto">
|
||||
<span class="input-group-text">Grid Size:</span>
|
||||
<input type="number" min="1" value="{{ grid_size }}" name="gridSize" id="gridSize" class="form-control form-control-sm">
|
||||
</div>
|
||||
<div class="vr mx-1"></div>
|
||||
<input type="color" class="form-control form-control-sm form-control-color" id="color">
|
||||
<div class="vr mx-1"></div>
|
||||
<div class="btn-group">
|
||||
|
|
@ -188,6 +198,10 @@ const exportEl = document.getElementById('export');
|
|||
const gridEl = document.getElementById('grid');
|
||||
const importButtonEl = document.getElementById('importButton');
|
||||
const importEl = document.getElementById('import');
|
||||
const gridSizeEl = document.getElementById('gridSize');
|
||||
|
||||
let gridSize = Number(gridSizeEl.value) || {{ grid_size }};
|
||||
let dotSize = Math.floor(Math.max(gridSize * 1.25, 32));
|
||||
|
||||
let ctx;
|
||||
let dpr = 1;
|
||||
|
|
@ -214,8 +228,24 @@ window.addEventListener('resize', resizeAndSetupCanvas);
|
|||
|
||||
setGrid();
|
||||
|
||||
function applyGridSize(newSize) {
|
||||
const n = Number(newSize);
|
||||
if (!Number.isFinite(n) || n < 1) return;
|
||||
|
||||
gridSize = n;
|
||||
document.documentElement.style.setProperty('--grid', `${gridSize}px`);
|
||||
|
||||
dotSize = Math.floor(Math.max(gridSize * 1.25, 32));
|
||||
|
||||
dotSVGEl.setAttribute('width', dotSize);
|
||||
dotSVGEl.setAttribute('height', dotSize);
|
||||
|
||||
setGrid();
|
||||
resizeAndSetupCanvas();
|
||||
}
|
||||
|
||||
function pxToGrid(v) {
|
||||
return v / {{ grid_size }};
|
||||
return v / gridSize;
|
||||
}
|
||||
|
||||
function getActiveTool() {
|
||||
|
|
@ -252,7 +282,7 @@ function snapToGrid(x, y) {
|
|||
const localX = clampedX - rect.left;
|
||||
const localY = clampedY - rect.top;
|
||||
|
||||
const grid = {{ grid_size }};
|
||||
const grid = gridSize;
|
||||
const maxIx = Math.floor(rect.width / grid);
|
||||
const maxIy = Math.floor(rect.height / grid);
|
||||
|
||||
|
|
@ -342,7 +372,7 @@ function redrawAll() {
|
|||
function drawShape(shape) {
|
||||
if (!ctx) return;
|
||||
|
||||
const toPx = (v) => v * {{ grid_size }};
|
||||
const toPx = (v) => v * gridSize;
|
||||
|
||||
ctx.save();
|
||||
ctx.strokeStyle = shape.color || '#000000';
|
||||
|
|
@ -411,11 +441,10 @@ function loadShapes() {
|
|||
function saveShapes() {
|
||||
try {
|
||||
localStorage.setItem('gridShapes', JSON.stringify(shapes));
|
||||
} catch {}
|
||||
} catch { }
|
||||
}
|
||||
|
||||
function setGrid() {
|
||||
const gridSize = {{ grid_size }};
|
||||
const type = getActiveType();
|
||||
|
||||
gridEl.style.backgroundImage = "";
|
||||
|
|
@ -472,6 +501,9 @@ document.querySelectorAll('input[name="gridType"]').forEach(input => {
|
|||
});
|
||||
});
|
||||
|
||||
gridSizeEl.addEventListener('input', () => applyGridSize(gridSizeEl.value));
|
||||
gridSizeEl.addEventListener('change', () => applyGridSize(gridSizeEl.value));
|
||||
|
||||
importButtonEl.addEventListener('click', () => importEl.click());
|
||||
|
||||
importEl.addEventListener('change', (e) => {
|
||||
|
|
@ -482,6 +514,12 @@ importEl.addEventListener('change', (e) => {
|
|||
reader.onload = () => {
|
||||
try {
|
||||
const data = JSON.parse(reader.result);
|
||||
|
||||
if (data.gridSize) {
|
||||
gridSizeEl.value = data.gridSize;
|
||||
applyGridSize(data.gridSize);
|
||||
}
|
||||
|
||||
const loadedShapes = Array.isArray(data) ? data : data.shapes;
|
||||
if (!Array.isArray(loadedShapes)) return;
|
||||
|
||||
|
|
@ -498,10 +536,10 @@ importEl.addEventListener('change', (e) => {
|
|||
exportEl.addEventListener('click', () => {
|
||||
const payload = {
|
||||
version: 1,
|
||||
gridSize: {{ grid_size }},
|
||||
gridSize: gridSize,
|
||||
shapes
|
||||
};
|
||||
const blob = new Blob([JSON.stringify(payload, null,2)], {type: 'application/json'});
|
||||
const blob = new Blob([JSON.stringify(payload, null, 2)], { type: 'application/json' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
|
|
@ -543,13 +581,16 @@ document.addEventListener('keydown', (e) => {
|
|||
});
|
||||
|
||||
gridEl.addEventListener('pointermove', (e) => {
|
||||
// Note to certain minds that keep thinking we want to mix grid and pixel coordinates.
|
||||
// No. No we do not. Pixels are not portable. Stop it.
|
||||
|
||||
if (!ctx) return;
|
||||
|
||||
const { ix, iy, x: snapX, y: snapY } = snapToGrid(e.clientX, e.clientY);
|
||||
|
||||
|
||||
const renderX = snapX - {{ dot_size }} / 2;
|
||||
const renderY = snapY - {{ dot_size }} / 2;
|
||||
const renderX = snapX - dotSize / 2;
|
||||
const renderY = snapY - dotSize / 2;
|
||||
|
||||
coordsEl.classList.remove('d-none');
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue