2RE03-Design/js/case-studies.js
2RE 53ca1fb834 Initial commit: 2RE03 portfolio site
Static HTML/CSS/JS portfolio for the design studio 2RE03: locally vendored Bootstrap 5.3.3, self-hosted Inter + Space Grotesk fonts, six pages, Collins-style scroll-snap carousels, a case-studies index with 10 detail pages, and a Web3Forms contact form.
2026-09-10 19:06:52 +08:00

68 lines
1.9 KiB
JavaScript

/* ==========================================================================
2RE03 case studies index
Cursor-following preview image for the typographic case-study list.
Progressive enhancement: without JS (or on touch/small screens) each row
shows its own inline thumbnail instead.
========================================================================== */
(function () {
"use strict";
var preview = document.querySelector("[data-case-preview]");
var rows = document.querySelectorAll("[data-case-image]");
if (!preview || !rows.length) {
return;
}
// Only run the floating preview for hover-capable, fine-pointer devices.
if (!window.matchMedia("(hover: hover) and (pointer: fine)").matches) {
return;
}
var frame = null;
var pointerX = 0;
var pointerY = 0;
function place() {
frame = null;
preview.style.left = pointerX + "px";
preview.style.top = pointerY + "px";
}
function onMove(event) {
pointerX = event.clientX;
pointerY = event.clientY;
if (!frame) {
frame = window.requestAnimationFrame(place);
}
}
function show(source) {
if (source) {
preview.src = source;
}
preview.classList.add("is-visible");
}
function hide() {
preview.classList.remove("is-visible");
}
Array.prototype.forEach.call(rows, function (row) {
var source = row.getAttribute("data-case-image");
row.addEventListener("mouseenter", function () { show(source); });
row.addEventListener("mousemove", onMove);
row.addEventListener("mouseleave", hide);
// Keyboard users get the preview pinned to the row.
row.addEventListener("focus", function () {
var box = row.getBoundingClientRect();
pointerX = box.left + box.width / 2;
pointerY = box.top + box.height / 2;
place();
show(source);
});
row.addEventListener("blur", hide);
});
})();