<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);

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.