JSFiddle - React, Tailwind, and code Playground

by HDL52

HTML

<section class="cards">
  <div class="card charizard"></div>
</section>
<style class="hover"></style>

CSS

html,
body {
  height: 100%;
  padding: 0;
  display: flex;
  justify-content: center;
  vertical-align: middle;
  transform: translate3d(0, 0, 0.1px);
}

.cards {
  display: flex;
  align-items: center;
  justify-content: center;
  perspective: 2000px;
  position: relative;
  z-index: 1;
  transform: translate3d(0.1px, 0.1px, 0.1px);
}

.card {
  --color1: rgb(255, 148, 54);
  --color2: rgb(255, 90, 144);

  width: 320px;
  height: 446px;
  background-color: #211799;
  background-image: url(https://raw.githubusercontent.com/Hongda-OSU/PicGo-2.3.1/master/imgpokemon_card_1.png);
  background-size: 100%;
  background-repeat: no-repeat;
  background-position: center;
  border-radius: 5% / 3.5%;
  position: relative;
  overflow: hidden;
  display: block;
  vertical-align: middle;
  margin: 20px 10px;
  animation: holoCard 15s ease infinite;
  transform-origin: center;
  z-index: 10;
  overflow: hidden;
  transform: translate3d(0, 0, -1px);
}

.card:before,
.card:after {
  content: "";
  opacity: 0.1;
  mix-blend-mode: screen;
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  top: 0;
  background-repeat: no-repeat;
}

.card:before {
  background-position: 50% 50%;
  background-size: 300% 300%;
  animation: holoGradient 15s ease infinite both;
  background-image: linear-gradient(
    115deg,
    transparent 0%,
    var(--color1) 30%,
    transparent 47.5%,
    transparent 52.5%,
    var(--color2) 70%,
    transparent 100%
  );
}

.card:after {
  opacity: 1;
  background-image: url("https://assets.codepen.io/13471/sparkles.gif");
  background-position: center;
  background-size: 160%;
  z-index: 2;
  animation: holoSparkle 15s ease infinite both;
  filter: brightness(1);
  transition: filter 0.5s ease;
}

.card.active {
  animation: none;
}

.card.active:before {
  opacity: 1;
  animation: none;
  transition: none;
  background-image: linear-gradient(
    115deg,
    transparent 30%,
    var(--color1) 48%,
    var(--color2) 53%,
    transparent 70%
  );
 ...

JavaScript

// 选择所有的卡片和样式元素
const cards = document.querySelectorAll(".card");
const style = document.querySelector(".hover");

cards.forEach(card => {
  card.addEventListener("mousemove", (e) => {
    const { offsetX: l, offsetY: t } = e;
    const { width: w, height: h } = card.getBoundingClientRect();
    console.log(card.getBoundingClientRect())
    const lp = Math.abs(Math.floor((100 / w) * l) - 100);
    const tp = Math.abs(Math.floor((100 / h) * t) - 100);
    const lp2 = (50 - Math.abs(Math.floor((100 / w) * l) - 100) / 10) + 5;
    const tp2 = (50 - Math.abs(Math.floor((100 / h) * t) - 100) / 10) + 5;
    const ty = (tp - 50) / 2;
    const tx = ((lp - 50) * 0.5) * -1;

    const bg = `background-position: ${lp}% ${tp}%;`;
    const bg2 = `background-position: ${lp2}% ${tp2}%;`;
    const tf = `transform: rotateX(${ty}deg) rotateY(${tx}deg);`;

    const dynamicStyle = `
      .card.active::before { ${bg} }
      .card.active::after { ${bg2} }
      .card.active { ${tf} }
    `;

    cards.forEach(c => c.classList.remove("active"));
    card.classList.add("active");
    style.innerHTML = dynamicStyle;
  });

  card.addEventListener("mouseout", () => {
    card.classList.remove("active");
  });
});