Some nice refinements here.
This commit is contained in:
parent
5b8f14c99b
commit
285db679d9
1 changed files with 33 additions and 13 deletions
|
|
@ -12,6 +12,8 @@
|
||||||
linear-gradient(to bottom, #ccc 1px, transparent 1px);
|
linear-gradient(to bottom, #ccc 1px, transparent 1px);
|
||||||
background-size: var(--grid) var(--grid);
|
background-size: var(--grid) var(--grid);
|
||||||
cursor: none;
|
cursor: none;
|
||||||
|
height: 80vh;
|
||||||
|
width: 100%;
|
||||||
height: calc(round(nearest, 80vh, var(--grid)) + 1px);
|
height: calc(round(nearest, 80vh, var(--grid)) + 1px);
|
||||||
width: calc(round(nearest, 100%, var(--grid)) + 1px);
|
width: calc(round(nearest, 100%, var(--grid)) + 1px);
|
||||||
}
|
}
|
||||||
|
|
@ -40,7 +42,7 @@
|
||||||
<div id="grid" class="position-relative overflow-hidden">
|
<div id="grid" class="position-relative overflow-hidden">
|
||||||
<div id="toolBar"
|
<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">
|
||||||
<input type="color" class="form-control form-control-sm form-control-color" id="color" oninput="setColor()">
|
<input type="color" class="form-control form-control-sm form-control-color" id="color">
|
||||||
<div class="vr mx-1"></div>
|
<div class="vr mx-1"></div>
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
<input type="radio" class="btn-check" id="outline" name="tool" checked>
|
<input type="radio" class="btn-check" id="outline" name="tool" checked>
|
||||||
|
|
@ -77,12 +79,14 @@
|
||||||
|
|
||||||
{% block script %}
|
{% block script %}
|
||||||
const canvasEl = document.getElementById('overlay');
|
const canvasEl = document.getElementById('overlay');
|
||||||
|
const colorEl = document.getElementById('color');
|
||||||
const coordsEl = document.getElementById('coords');
|
const coordsEl = document.getElementById('coords');
|
||||||
const dotEl = document.getElementById('dot');
|
const dotEl = document.getElementById('dot');
|
||||||
const dotSVGEl = document.getElementById('dotSVG');
|
const dotSVGEl = document.getElementById('dotSVG');
|
||||||
const gridEl = document.getElementById('grid');
|
const gridEl = document.getElementById('grid');
|
||||||
|
|
||||||
let ctx;
|
let ctx;
|
||||||
|
let dpr = 1;
|
||||||
let selectedColor = '#000000';
|
let selectedColor = '#000000';
|
||||||
|
|
||||||
let currentRect = null;
|
let currentRect = null;
|
||||||
|
|
@ -92,7 +96,7 @@
|
||||||
window.addEventListener('resize', resizeAndSetupCanvas);
|
window.addEventListener('resize', resizeAndSetupCanvas);
|
||||||
|
|
||||||
function snapToGrid(x, y) {
|
function snapToGrid(x, y) {
|
||||||
const rect = canvasEl.getBoundingClientRect();
|
const rect = gridEl.getBoundingClientRect();
|
||||||
const clampedX = Math.min(Math.max(x, rect.left), rect.right);
|
const clampedX = Math.min(Math.max(x, rect.left), rect.right);
|
||||||
const clampedY = Math.min(Math.max(y, rect.top), rect.bottom);
|
const clampedY = Math.min(Math.max(y, rect.top), rect.bottom);
|
||||||
|
|
||||||
|
|
@ -115,12 +119,13 @@
|
||||||
y: Math.min(rect.y1, rect.y2),
|
y: Math.min(rect.y1, rect.y2),
|
||||||
w: Math.abs(rect.x2 - rect.x1),
|
w: Math.abs(rect.x2 - rect.x1),
|
||||||
h: Math.abs(rect.y2 - rect.y1),
|
h: Math.abs(rect.y2 - rect.y1),
|
||||||
color: rect.color
|
color: rect.color,
|
||||||
|
fill: rect.fill
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function resizeAndSetupCanvas() {
|
function resizeAndSetupCanvas() {
|
||||||
const dpr = window.devicePixelRatio || 1;
|
dpr = window.devicePixelRatio || 1;
|
||||||
const rect = canvasEl.getBoundingClientRect();
|
const rect = canvasEl.getBoundingClientRect();
|
||||||
|
|
||||||
canvasEl.width = rect.width * dpr;
|
canvasEl.width = rect.width * dpr;
|
||||||
|
|
@ -140,32 +145,46 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawRect(rect) {
|
function drawRect(rect) {
|
||||||
|
ctx.save();
|
||||||
|
|
||||||
ctx.strokeStyle = rect.color;
|
ctx.strokeStyle = rect.color;
|
||||||
ctx.strokeRect(rect.x, rect.y, rect.w, rect.h);
|
ctx.strokeRect(rect.x, rect.y, rect.w, rect.h);
|
||||||
|
|
||||||
if (rect.fill) {
|
if (rect.fill) {
|
||||||
ctx.globalAlpha = 0.15;
|
ctx.globalAlpha = 0.15;
|
||||||
ctx.fillStyle = rect.color;
|
ctx.fillStyle = rect.color;
|
||||||
ctx.fillRect(rect.x, rect.y, rect.w, rect.h);
|
ctx.fillRect(rect.x, rect.y, rect.w, rect.h);
|
||||||
ctx.globalAlpha = 1;
|
ctx.globalAlpha = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearCanvas() {
|
function clearCanvas() {
|
||||||
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
ctx.clearRect(0, 0, canvasEl.width / dpr, canvasEl.height / dpr);
|
||||||
ctx.clearRect(0, 0, canvasEl.width, canvasEl.height);
|
|
||||||
const dpr = window.devicePixelRatio || 1;
|
|
||||||
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
window.setColor = function setColor() {
|
colorEl.addEventListener('input', () => {
|
||||||
selectedColor = document.getElementById('color').value;
|
selectedColor = document.getElementById('color').value;
|
||||||
|
const circle = dotSVGEl.querySelector('circle');
|
||||||
|
if (circle) {
|
||||||
|
circle.setAttribute('fill', selectedColor);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
document.addEventListener('keydown', (e) => {
|
document.addEventListener('keydown', (e) => {
|
||||||
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'z') {
|
const key = e.key.toLowerCase();
|
||||||
|
|
||||||
|
if ((e.ctrlKey || e.metaKey) && key === 'z') {
|
||||||
|
e.preventDefault();
|
||||||
rects.pop();
|
rects.pop();
|
||||||
redrawAll();
|
redrawAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (key === 'escape' && currentRect) {
|
||||||
|
currentRect = null;
|
||||||
|
redrawAll();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
gridEl.addEventListener('mousemove', (e) => {
|
gridEl.addEventListener('mousemove', (e) => {
|
||||||
|
|
@ -216,11 +235,12 @@
|
||||||
y1: snapY,
|
y1: snapY,
|
||||||
x2: snapX,
|
x2: snapX,
|
||||||
y2: snapY,
|
y2: snapY,
|
||||||
color: selectedColor
|
color: selectedColor,
|
||||||
|
fill: document.getElementById('filled').checked
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
gridEl.addEventListener('mouseup', (e) => {
|
window.addEventListener('mouseup', (e) => {
|
||||||
if (!currentRect) return;
|
if (!currentRect) return;
|
||||||
|
|
||||||
const {ix, iy, x: snapX, y: snapY } = snapToGrid(e.clientX, e.clientY);
|
const {ix, iy, x: snapX, y: snapY } = snapToGrid(e.clientX, e.clientY);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue