Микровзаимодействия
Превью у ссылок
Наводишь на пункт списка работ — рядом с курсором всплывает фото проекта и следует за ним.
Наводите на пункты списка.
Код
<div class="works">
<a href="/case-1" data-prev="a.jpg">Кейс один</a>
<a href="/case-2" data-prev="b.jpg">Кейс два</a>
<img class="preview" alt="">
</div>
<style>
.works { position: relative; }
.works a { position: relative; z-index: 2; }
.preview { position: absolute; width: 230px; aspect-ratio: 3/4;
object-fit: cover; pointer-events: none; z-index: 1;
translate: -50% -50%; opacity: 0;
transform: scale(.85) rotate(-3deg);
transition: opacity .3s, transform .4s cubic-bezier(.16,1,.3,1); }
.works.on .preview { opacity: 1; transform: scale(1) rotate(3deg); }
</style>
<script>
var stage = document.querySelector(".works");
var img = stage.querySelector(".preview");
var tx = 0, ty = 0, cx = 0, cy = 0;
stage.addEventListener("pointermove", function (e) {
var r = stage.getBoundingClientRect();
tx = e.clientX - r.left; ty = e.clientY - r.top;
});
(function loop() { // картинка догоняет курсор
cx += (tx - cx) * .12; cy += (ty - cy) * .12;
img.style.left = cx + "px"; img.style.top = cy + "px";
requestAnimationFrame(loop);
})();
stage.querySelectorAll("[data-prev]").forEach(function (a) {
a.addEventListener("pointerenter", function () {
img.src = a.getAttribute("data-prev");
stage.classList.add("on");
});
a.addEventListener("pointerleave", function () {
stage.classList.remove("on");
});
});
</script>
Промпт для ИИ
Сделай всплывающее превью у списка ссылок (портфолио-приём): в контейнере — absolute img (230px, 3/4, скругление, pointer-events none, z-index ниже ссылок), спрятанный opacity 0 + scale .85 rotate(-3deg). На pointerenter ссылки: img.src из data-prev, контейнеру класс on → превью проявляется в scale 1 rotate(3deg). Картинка следует за курсором с лерпом 0.12 в rAF (запаздывание — обязательно). На pointerleave — прячется. На тач-устройствах отключить.