137 lines
4.0 KiB
HTML
137 lines
4.0 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>CSS Holographic Card Demo</title>
|
|
<style>
|
|
:root {
|
|
--color1: #00e7ff;
|
|
--color2: #ff00e7;
|
|
--back: #1a1a1a;
|
|
}
|
|
|
|
body {
|
|
background-color: var(--back);
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
height: 100vh;
|
|
margin: 0;
|
|
font-family: sans-serif;
|
|
}
|
|
|
|
/* 卡片容器:设置透视距离 */
|
|
.card-container {
|
|
perspective: 1000px;
|
|
}
|
|
|
|
/* 卡片主体 */
|
|
.card {
|
|
width: 320px;
|
|
height: 450px;
|
|
position: relative;
|
|
border-radius: 15px;
|
|
background-image: url('https://images.pokemontcg.io/swsh4/25_hires.png'); /* 示例卡面 */
|
|
background-size: cover;
|
|
background-position: center;
|
|
box-shadow: 0 0 20px rgba(0,0,0,0.5);
|
|
|
|
/* 关键:通过 JS 更新变量 */
|
|
transform: rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
|
|
transition: transform 0.1s ease-out;
|
|
|
|
overflow: hidden;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
|
|
/* 全息层:彩虹光泽 */
|
|
.card::before {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 0;
|
|
z-index: 2;
|
|
|
|
/* 核心:利用渐变和混合模式 */
|
|
background: linear-gradient(
|
|
115deg,
|
|
transparent 20%,
|
|
var(--color1) 36%,
|
|
var(--color2) 43%,
|
|
var(--color1) 50%,
|
|
var(--color2) 57%,
|
|
var(--color1) 64%,
|
|
transparent 80%
|
|
);
|
|
background-size: 300% 300%;
|
|
background-position: var(--pos-x, 50%) var(--pos-y, 50%);
|
|
|
|
/* 混合模式:这是全息感的来源 */
|
|
mix-blend-mode: color-dodge;
|
|
opacity: var(--opacity, 0);
|
|
transition: opacity 0.3s;
|
|
}
|
|
|
|
/* 光斑层:模拟点光源直射 */
|
|
.card::after {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 0;
|
|
z-index: 3;
|
|
background: radial-gradient(
|
|
circle at var(--pos-x, 50%) var(--pos-y, 50%),
|
|
rgba(255, 255, 255, 0.6) 0%,
|
|
transparent 60%
|
|
);
|
|
mix-blend-mode: overlay;
|
|
opacity: var(--opacity, 0);
|
|
transition: opacity 0.3s;
|
|
}
|
|
|
|
.card:hover {
|
|
cursor: pointer;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<div class="card-container">
|
|
<div class="card" id="card"></div>
|
|
</div>
|
|
|
|
<script>
|
|
const card = document.getElementById('card');
|
|
|
|
card.addEventListener('mousemove', (e) => {
|
|
const rect = card.getBoundingClientRect();
|
|
|
|
// 计算鼠标在卡片上的相对坐标 (0 to 1)
|
|
const x = (e.clientX - rect.left) / rect.width;
|
|
const y = (e.clientY - rect.top) / rect.height;
|
|
|
|
// 计算旋转角度 (最大旋转 20 度)
|
|
const rx = (y - 0.5) * -40; // 垂直旋转
|
|
const ry = (x - 0.5) * 40; // 水平旋转
|
|
|
|
// 计算渐变背景的位置 (根据鼠标反向移动增加灵动感)
|
|
const posX = 100 - x * 100;
|
|
const posY = 100 - y * 100;
|
|
|
|
// 更新 CSS 变量
|
|
card.style.setProperty('--rx', `${rx}deg`);
|
|
card.style.setProperty('--ry', `${ry}deg`);
|
|
card.style.setProperty('--pos-x', `${posX}%`);
|
|
card.style.setProperty('--pos-y', `${posY}%`);
|
|
card.style.setProperty('--opacity', `1`);
|
|
});
|
|
|
|
// 鼠标移出重置
|
|
card.addEventListener('mouseleave', () => {
|
|
card.style.setProperty('--rx', `0deg`);
|
|
card.style.setProperty('--ry', `0deg`);
|
|
card.style.setProperty('--opacity', `0`);
|
|
});
|
|
</script>
|
|
</body>
|
|
</html> |