<section class="hero">
<div class="container">
<figure class="hero__fig">
<img class="hero__image hero__image--bottom" src="https://images.unsplash.com/photo-1519052537078-e6302a4968d4?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=870&h=500&q=80" alt="">
<img class="hero__image hero__image--top" src="https://images.unsplash.com/photo-1494256997604-768d1f608cac?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=870&h=500&q=80" alt="">
</figure>
</div>
</section>
body {
margin: 0;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.hero__fig {
position: relative;
margin: 0;
}
.hero__image {
display: block;
width: 100%;
}
.hero__image--top {
position: absolute;
inset: 0;
}
const lerp = (a, b, t) => a * (1 - t) + b * t;
function rotate(x, y, a) {
const sin = Math.sin(a);
const cos = Math.cos(a);
return [cos * x - sin * y, sin * x + cos * y];
}
const SQUARE_SIZE = 150;
const RADIUS_MIN = 100;
const RADIUS_MAX = 350;
const ROT_SPEED = 0.001;
const SMOOTH_COEF = 0.05;
const figureEl = document.querySelector(".hero__fig");
const topImgEl = figureEl.querySelector(".hero__image--top");
const bottomImgEl = figureEl.querySelector(".hero__image--bottom");
const figureRect = { x: 0, y: 0, w: 0, h: 0 };
function onResize() {
const rect = figureEl.getBoundingClientRect();
figureRect.x = rect.x;
figureRect.y = rect.y;
figureRect.w = rect.width;
figureRect.h = rect.height;
}
onResize();
window.addEventListener("resize", onResize);
const mouse = {
current: { x: figureRect.w / 2, y: figureRect.h / 2 },
target: { x: figureRect.w / 2, y: figureRect.h / 2 }
};
const radius = {
current: RADIUS_MIN,
target: RADIUS_MIN
};
function onMouseMove(event) {
mouse.target.x = event.clientX - figureRect.x;
mouse.target.y = event.clientY - figureRect.y;
}
figureEl.addEventListener("mousemove", onMouseMove);
function onMouseLeave() {
mouse.target.x = figureRect.w / 2;
mouse.target.y = figureRect.h / 2;
}
figureEl.addEventListener("mouseleave", onMouseLeave);
function rafLoop(now) {
const mouseSpeed = Math.hypot(
mouse.current.x - mouse.target.x,
mouse.current.y - mouse.target.y
);
const mouseSpeedNorm = Math.min(1, mouseSpeed / 500);
radius.target = lerp(RADIUS_MIN, RADIUS_MAX, mouseSpeedNorm);
radius.current = lerp(radius.current, radius.target, SMOOTH_COEF);
mouse.current.x = lerp(mouse.current.x, mouse.target.x, SMOOTH_COEF);
mouse.current.y = lerp(mouse.current.y, mouse.target.y, SMOOTH_COEF);
const tlX = mouse.current.x - SQUARE_SIZE / 2;
const tlY = mouse.current.y - SQUARE_SIZE / 2;
const trX = mouse.current.x + SQUARE_SIZE / 2;
const trY = mouse.current.y - SQUARE_SIZE / 2;
const brX = mouse.current.x + SQUARE_SIZE / 2;
const brY = mouse.current.y + SQUARE_SIZE / 2;
const blX = mouse.current.x - SQUARE_SIZE / 2;
const blY = mouse.current.y + SQUARE_SIZE / 2;
let clipPath = "";
const total = 3;
for (let i = 0; i < total; i++) {
const angle = (Math.PI * 2 * i) / total + now * ROT_SPEED;
const [dx, dy] = rotate(0, radius.current, angle);
clipPath +=
`M ${tlX + dx} ${tlY + dy}, ` +
`L ${trX + dx} ${trY + dy}, ` +
`L ${brX + dx} ${brY + dy}, ` +
`L ${blX + dx} ${blY + dy} `;
}
topImgEl.style.clipPath = `path("${clipPath}")`;
requestAnimationFrame(rafLoop);
}
requestAnimationFrame(rafLoop);
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.