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