JSFiddle - React, Tailwind, and code Playground
by gabihp30
HTML
<img width="750" height="750" src="https://pixijs.io/examples/examples/assets/bg_rotate.jpg" id="screenshot" draggable="false">
<svg width="750" height="750" viewBox="0 0 750 750" id="draw" xmlns="http://www.w3.org/2000/svg">
<rect id="marquee" x="450" y="420" width="150" height="150" />
<g id="boxes"></g>
</svg>
CSS
#screenshot {
position:absolute;
z-index:1;
}
#draw {
position:absolute;
z-index:2;
pointer-events:none;
}
#draw #boxes {
fill:blue;
stroke:white;
stroke-width:1;
fill-opacity:0.5;
stroke-opacity:0.9;
}
#draw #marquee {
fill:white;
stroke:red;
stroke-width:1;
stroke-dasharray:5,5;
stroke-opacity:0.9;
fill-opacity:0.2;
}
#draw #marquee.hide {
display:none;
}
JavaScript
const $ = document.querySelector.bind(document);
/**
* Collection of rectangles defining user generated regions
*/
const rectangles = [];
// DOM elements
const $screenshot = $('#screenshot');
const $draw = $('#draw');
const $marquee = $('#marquee');
const $boxes = $('#boxes');
// Temp variables
let startX = 0;
let startY = 0;
const marqueeRect = {
x: 0,
y: 0,
width: 0,
height: 0,
};
$marquee.classList.add('hide');
$screenshot.addEventListener('pointerdown', startDrag);
function startDrag(ev) {
// middle button delete rect
if (ev.button === 1) {
const rect = hitTest(ev.layerX, ev.layerY);
if (rect) {
rectangles.splice(rectangles.indexOf(rect), 1);
redraw();
}
return;
}
window.addEventListener('pointerup', stopDrag);
$screenshot.addEventListener('pointermove', moveDrag);
$marquee.classList.remove('hide');
startX = ev.layerX;
startY = ev.layerY;
drawRect($marquee, startX, startY, 0, 0);
}
function stopDrag(ev) {
$marquee.classList.add('hide');
window.removeEventListener('pointerup', stopDrag);
$screenshot.removeEventListener('pointermove', moveDrag);
if (ev.target === $screenshot && marqueeRect.width && marqueeRect.height) {
rectangles.push(Object.assign({}, marqueeRect));
redraw();
}
}
function moveDrag(ev) {
let x = ev.layerX;
let y = ev.layerY;
let width = startX - x;
let height = startY - y;
if (width < 0) {
width *= -1;
x -= width;
}
if (height < 0) {
height *= -1;
y -= height;
}
Object.assign(marqueeRect, { x, y, width, height });
drawRect($marquee, marqueeRect);
}
function hitTest(x, y) {
return rectangles.find(rect => (
x >= rect.x &&
y >= rect.y &&
x <= rect.x + rect.width &&
y <= rect.y + rect.height
));
}
function redraw() {
boxes.innerHTML = '';
rectangles.forEach((data) => {
boxes.appendChild(drawRect(
document.createElementNS("http://www.w3.org/2000/svg", 'rect'), data
));
});
}
function drawRect(rect, data)...