Improve card image hover: center small, pan large

This commit is contained in:
2026-02-02 23:42:07 +01:00
parent 2add818045
commit eee4f1f0e9
2 changed files with 48 additions and 0 deletions

View File

@@ -543,6 +543,7 @@ function buildCard(s, { showAuthor = false, allowDelete = false, allowEdit = fal
`;
if (hasImage) {
const btn = card.querySelector(".card-visual");
setupCardVisualHover(btn, s.screenshotUrl);
btn.addEventListener("click", () => openLightbox(s.screenshotUrl, s.name));
}
if (allowEdit) {
@@ -669,6 +670,50 @@ function openLightbox(url, title) {
document.body.appendChild(overlay);
}
function setupCardVisualHover(el, url) {
if (!el || !url) return;
const img = new Image();
let naturalW = 0;
let naturalH = 0;
let loaded = false;
img.src = url;
img.onload = () => {
naturalW = img.naturalWidth;
naturalH = img.naturalHeight;
loaded = true;
};
const reset = () => {
el.classList.remove("hovering");
el.style.backgroundSize = "";
el.style.backgroundPosition = "";
};
el.addEventListener("mouseenter", () => {
el.classList.add("hovering");
el.style.backgroundSize = "auto";
el.style.backgroundPosition = "center";
});
el.addEventListener("mousemove", (e) => {
if (!loaded) return;
const rect = el.getBoundingClientRect();
const overW = naturalW - rect.width;
const overH = naturalH - rect.height;
if (overW <= 0 && overH <= 0) {
el.style.backgroundPosition = "center";
return;
}
const xRatio = (e.clientX - rect.left) / rect.width;
const yRatio = (e.clientY - rect.top) / rect.height;
const xPercent = overW > 0 ? xRatio * 100 : 50;
const yPercent = overH > 0 ? yRatio * 100 : 50;
el.style.backgroundPosition = `${xPercent}% ${yPercent}%`;
});
["mouseleave", "blur"].forEach(evt => el.addEventListener(evt, reset));
}
async function main() {
setupHandlers();
try {

View File

@@ -161,12 +161,15 @@ button.ghost { background: transparent; border-color: #d5c7b5; color: #2c1c0d; }
background: linear-gradient(135deg, #f0d9b5, #f6b24f);
background-size: cover;
background-position: center;
background-repeat: no-repeat;
background-color: #f6b24f;
cursor: pointer;
border: none;
width: 100%;
display: block;
padding: 0;
}
.card-visual.hovering { cursor: zoom-in; }
.card-body { padding: 12px; display: flex; flex-direction: column; gap: 6px; flex: 1; }