'How can I highlight the box as I'm creating it?
Currently the box only appears after you stop dragging. I want to outline the box as its being created.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Billion Satoshis</title>
<script type="module">
let cells = Math.pow(256, 2);
document.addEventListener("DOMContentLoaded", main);
function main() {
const view = document.getElementById("scroller");
const grid = [];
for (let i = 0; i < cells; i++) {
const el = document.createElement("div");
el.classList.add("cell");
grid.push(el);
}
view.append(...grid);
view.style.gridTemplateColumns = `repeat(${Math.sqrt(cells)}, 10px)`;
/* added */
const selectionLayer = document.getElementById("selectionLayer");
let isMouseDown = false;
let isMultiSelectionOn = false;
let selectionStart = {},
selectionEnd = {};
let selectionRect = {};
let scrollBarCorrection_x = view.offsetWidth - view.clientWidth;
let scrollBarCorrection_y = view.offsetHeight - view.clientHeight;
let selectionMargin = {
width: 10,
height: 5,
};
view.addEventListener("mousedown", (e) => {
isMouseDown = true;
if (!isMultiSelectionOn) {
selectionEnd = {
x: null,
y: null,
};
clearSecelction();
}
selectionStart = {
x: e.x - view.offsetLeft,
y: e.y - view.offsetTop,
};
});
view.addEventListener("mouseup", (e) => {
isMouseDown = false;
selectionEnd = {
x: e.x - view.offsetLeft,
y: e.y - view.offsetTop,
};
if (
Math.abs(selectionEnd.x - selectionStart.x) <
selectionMargin.width ||
Math.abs(selectionEnd.y - selectionStart.y) < selectionMargin.height
)
return;
selectionLayer.style.top = `0px`;
selectionLayer.style.left = `0px`;
selectionLayer.style.bottom = "unset";
selectionLayer.style.right = "unset";
selectionLayer.style.visibility = "hidden";
getSelectedCells().forEach((c) => c.classList.add("selected"));
});
view.addEventListener("mousemove", (e) => {
if (!isMouseDown) return;
selectionEnd = {
x: e.x,
y: e.y,
};
selectionRect = {
x1: Math.min(selectionStart.x, selectionEnd.x),
y1: Math.min(selectionStart.y, selectionEnd.y),
x2:
Math.max(selectionStart.x, selectionEnd.x) +
scrollBarCorrection_x,
y2:
Math.max(selectionStart.y, selectionEnd.y) +
scrollBarCorrection_y,
};
selectionLayer.style.top = `${Math.min(
selectionRect.y1,
selectionRect.y2
)}px`;
selectionLayer.style.left = `${Math.min(
selectionRect.x1,
selectionRect.x2
)}px`;
selectionLayer.style.bottom = `${
view.offsetHeight +
view.offsetTop -
Math.max(selectionRect.y1, selectionRect.y2)
}px`;
selectionLayer.style.right = `${
view.offsetWidth +
view.offsetLeft -
Math.max(selectionRect.x1, selectionRect.x2)
}px`;
selectionLayer.style.visibility = "visible";
if (!isMultiSelectionOn) clearSecelction();
});
function clearSecelction() {
view
.querySelectorAll(".cell")
.forEach((c) => c.classList.remove("selected"));
}
function getSelectedCells() {
let selectedCells = [];
const cells = view.querySelectorAll(".cell");
cells.forEach((c) => {
const bounds = c.getBoundingClientRect();
selectionLayer.style.visibility = "visible";
if (
selectionRect.x1 <= bounds.left - view.offsetLeft &&
selectionRect.y1 <= bounds.top - view.offsetTop &&
selectionRect.x2 - scrollBarCorrection_x >=
bounds.right - view.offsetLeft &&
selectionRect.y2 - scrollBarCorrection_y >= bounds.bottom
)
selectedCells.push(c);
});
return selectedCells;
}
document.addEventListener("keydown", (e) => {
if (e.ctrlKey) isMultiSelectionOn = true;
});
document.addEventListener("keyup", (e) => {
if (!e.ctrlKey) isMultiSelectionOn = false;
});
document.addEventListener("resize", () => {
scrollBarCorrection_x = view.offsetWidth - view.clientWidth;
scrollBarCorrection_y = view.offsetHeight - view.clientHeight;
});
}
</script>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
font-size: 62.5%;
}
body {
font-size: 1.6rem;
font-family: sans-serif;
}
h1 {
font-size: 2rem;
}
#view {
width: calc(100vw - 2rem);
height: calc(100vh - 10rem);
margin: auto;
background-color: #eee;
border: 1px solid black;
overflow: auto;
display: grid;
gap: 0;
border-top: 1px solid black;
border-left: 1px solid black;
position: relative;
user-select: none;
}
header {
text-align: center;
}
.cell {
width: 1rem;
height: 1rem;
border-right: 1px solid black;
border-bottom: 1px solid black;
}
.cell.selected {
background-color: #5eba7d;
}
#scroller {
position: absolute;
height: 100%;
width: 100%;
display: grid;
grid-template-columns: repeat(640, 10px);
gap: 0;
}
#selectionLayer {
position: absolute;
top: 0px;
left: 0px;
border: 1px solid #5eba7d;
background-color: #5eba7d45;
z-index: 99999;
}
</style>
</head>
<body>
<header>
<h1>Billion Satoshis</h1>
<p>Pixel based advertising for crypto</p>
<p><small>$1/square (svg only)</small></p>
</header>
<section id="view">
<div id="scroller">
<div id="selectionLayer"></div>
</div>
</section>
</body>
</html>
JSFiddel: https://jsfiddle.net/chovy/cs36ykrm/
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
