御坂美琴的"电击使"特点,又保持了卡片的优雅美感。电子线条的流动效果和鼠标交互的即时响应为用户提供了沉浸式的视觉体验。
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>御坂美琴主题电子特效卡片</title>
<style>
:root {
--electric-border-color: #44ddff;
--electric-primary: #00aaff;
--electric-secondary: #00eeff;
--electric-accent: #aa00ff;
--electric-bg: #0a0a1a;
}
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: system-ui, -apple-system, sans-serif;
background-color: var(--electric-bg);
color: oklch(0.985 0 0);
min-height: 100vh;
overflow: hidden;
position: relative;
}
/* 电子背景层 */
.electric-background {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
opacity: 0.4;
filter: blur(0.5px);
}
/* 电子线条 */
.electric-line {
position: absolute;
background: linear-gradient(90deg,
transparent,
var(--electric-primary),
var(--electric-secondary),
transparent);
height: 1px;
box-shadow: 0 0 8px var(--electric-primary), 0 0 12px var(--electric-secondary);
border-radius: 2px;
animation: electric-flow 4s linear infinite;
}
/* 电子节点 */
.electric-node {
position: absolute;
width: 6px;
height: 6px;
border-radius: 50%;
background-color: var(--electric-secondary);
box-shadow: 0 0 8px var(--electric-secondary), 0 0 12px var(--electric-primary);
animation: electric-pulse 2s ease-in-out infinite;
}
.container {
display: grid;
place-content: center;
min-height: 100vh;
padding: 2rem;
}
.card {
font-size: 16px;
border-radius: 1.5em;
position: relative;
width: 700px;
max-width: 90vw;
transition: transform 0.3s ease;
cursor: pointer;
}
/* 悬停抖动效果 */
.card:hover {
animation: electric-shake 0.3s ease-in-out;
}
.card__layer {
position: absolute;
inset: 0;
border-radius: inherit;
pointer-events: none;
}
.card__layer--main {
border: 2px solid oklch(from var(--electric-border-color) l c h / 0.5);
background: rgba(10, 10, 30, 0.7);
backdrop-filter: blur(10px);
}
.card__layer--main::after {
content: "";
position: absolute;
inset: -2px;
border: 2px solid var(--electric-border-color);
border-radius: inherit;
opacity: 1;
transition: opacity 0.3s ease;
}
.card:hover .card__layer--main::after {
opacity: 1;
margin-top: -4px;
margin-left: -4px;
filter: url(#turbulent-displace);
}
.card__layer--glow-tight {
border: 2px solid oklch(from var(--electric-border-color) l c h / 0.6);
filter: blur(1px);
}
.card__layer--glow-wide {
border: 2px solid var(--electric-border-color);
filter: blur(4px);
}
.card__layer--overlay-primary {
background: linear-gradient(
-30deg,
white,
transparent 30%,
transparent 70%,
white
);
transform: scale(1.1);
filter: blur(16px);
mix-blend-mode: overlay;
}
.card__layer--overlay-secondary {
opacity: 0.5;
background: linear-gradient(
-30deg,
white,
transparent 30%,
transparent 70%,
white
);
transform: scale(1.1);
filter: blur(16px);
mix-blend-mode: overlay;
}
.card__layer--background-glow {
background: linear-gradient(
-30deg,
var(--electric-border-color),
transparent,
var(--electric-border-color)
);
filter: blur(32px);
transform: scale(1.1);
opacity: 0.2;
}
/* 卡片电子效果覆盖层 */
.card__electric-overlay {
position: absolute;
inset: 0;
border-radius: inherit;
pointer-events: none;
overflow: hidden;
opacity: 0;
transition: opacity 0.3s ease;
}
.card:hover .card__electric-overlay {
opacity: 1;
}
.card__electric-line {
position: absolute;
background: linear-gradient(90deg,
transparent,
var(--electric-secondary),
var(--electric-primary),
transparent);
height: 1px;
box-shadow: 0 0 6px var(--electric-primary), 0 0 10px var(--electric-secondary);
border-radius: 1px;
animation: card-electric-flow 2s linear infinite;
}
.card__electric-spark {
position: absolute;
width: 4px;
height: 4px;
border-radius: 50%;
background-color: var(--electric-secondary);
box-shadow: 0 0 6px var(--electric-secondary), 0 0 10px var(--electric-primary);
animation: electric-spark 1.5s ease-in-out infinite;
}
.card__content {
display: flex;
flex-direction: column;
gap: 1em;
padding: 3em;
position: relative;
z-index: 1;
}
.card__title {
font-size: 2.25em;
font-weight: 500;
line-height: 1.5;
text-shadow: 0 0 10px rgba(68, 221, 255, 0.5);
}
.card__recipient {
opacity: 0.8;
text-align: end;
font-size: 1.2em;
text-shadow: 0 0 5px rgba(68, 221, 255, 0.5);
}
.card__divider {
border: none;
height: 1px;
background-color: currentColor;
opacity: 0.2;
width: 80%;
margin-inline: auto;
mask-image: linear-gradient(to right, transparent, black, transparent);
}
/* 动画定义 */
@keyframes electric-flow {
0% {
opacity: 0.3;
transform: translateX(-100%);
}
10% {
opacity: 1;
}
90% {
opacity: 1;
}
100% {
opacity: 0.3;
transform: translateX(100vw);
}
}
@keyframes card-electric-flow {
0% {
opacity: 0.3;
transform: translateX(-100%);
}
10% {
opacity: 1;
}
90% {
opacity: 1;
}
100% {
opacity: 0.3;
transform: translateX(100%);
}
}
@keyframes electric-pulse {
0%, 100% {
opacity: 0.3;
transform: scale(1);
box-shadow: 0 0 8px var(--electric-secondary), 0 0 12px var(--electric-primary);
}
50% {
opacity: 1;
transform: scale(1.2);
box-shadow: 0 0 12px var(--electric-secondary), 0 0 20px var(--electric-primary);
}
}
@keyframes electric-spark {
0%, 100% {
opacity: 0.3;
transform: scale(1);
box-shadow: 0 0 6px var(--electric-secondary), 0 0 10px var(--electric-primary);
}
50% {
opacity: 1;
transform: scale(1.5);
box-shadow: 0 0 10px var(--electric-secondary), 0 0 16px var(--electric-primary), 0 0 20px var(--electric-accent);
}
}
@keyframes electric-shake {
0%, 100% {
transform: translateX(0) translateY(0);
}
10%, 30%, 50%, 70%, 90% {
transform: translateX(-1px) translateY(-1px);
}
20%, 40%, 60%, 80% {
transform: translateX(1px) translateY(1px);
}
}
/* 响应式调整 */
@media (max-width: 768px) {
.card {
width: 90vw;
}
.card__content {
padding: 2em;
}
.card__title {
font-size: 1.8em;
}
}
</style>
</head>
<body>
<!-- 电子背景层 -->
<div class="electric-background" id="electricBackground"></div>
<main class="container">
<div class="card">
<div class="card__layer card__layer--main"></div>
<div class="card__layer card__layer--glow-tight"></div>
<div class="card__layer card__layer--glow-wide"></div>
<div class="card__layer card__layer--overlay-primary"></div>
<div class="card__layer card__layer--overlay-secondary"></div>
<div class="card__layer card__layer--background-glow"></div>
<!-- 卡片电子效果覆盖层 -->
<div class="card__electric-overlay" id="cardElectricOverlay"></div>
<div class="card__content">
<h1 class="card__title">
"你指尖跃动的电光<br />是我此生不灭的信仰"
</h1>
<hr class="card__divider" />
<p class="card__recipient">
TO:御坂美琴
</p>
</div>
<svg width="0" height="0">
<defs>
<filter id="turbulent-displace" color-interpolation-filters="sRGB" x="-20%" y="-20%" width="140%" height="140%">
<feTurbulence type="turbulence" baseFrequency="0.02" numOctaves="10" seed="1" result="verticalNoise" />
<feOffset in="verticalNoise" result="animatedVertical_1">
<animate id="animate-dy-1" attributeName="dy" values="700; 0" dur="4s" repeatCount="indefinite" />
</feOffset>
<feOffset in="verticalNoise" result="animatedVertical_2">
<animate id="animate-dy-2" attributeName="dy" values="0; -700" dur="4s" repeatCount="indefinite" />
</feOffset>
<feComposite in="animatedVertical_1" in2="animatedVertical_2" operator="over" result="seamlessVerticalNoise" />
<feTurbulence type="turbulence" baseFrequency="0.02" numOctaves="10" seed="2" result="horizontalNoise" />
<feOffset in="horizontalNoise" result="animatedHorizontal_1">
<animate id="animate-dx-1" attributeName="dx" values="400; 0" dur="4s" repeatCount="indefinite" />
</feOffset>
<feOffset in="horizontalNoise" result="animatedHorizontal_2">
<animate id="animate-dx-2" attributeName="dx" values="0; -400" dur="4s" repeatCount="indefinite" />
</feOffset>
<feComposite in="animatedHorizontal_1" in2="animatedHorizontal_2" operator="over" result="seamlessHorizontalNoise" />
<feBlend in="seamlessVerticalNoise" in2="seamlessHorizontalNoise" mode="color-dodge" result="finalBlendedNoise" />
<feDisplacementMap in="SourceGraphic" in2="finalBlendedNoise" scale="30" xChannelSelector="R" yChannelSelector="B" />
</filter>
</defs>
</svg>
</div>
</main>
<script>
// 创建背景电子效果
function createElectricBackground() {
const background = document.getElementById('electricBackground');
// 创建电子线条
for (let i = 0; i < 20; i++) {
const line = document.createElement('div');
line.className = 'electric-line';
// 随机位置和属性
const top = Math.random() * 100;
const width = 50 + Math.random() * 150;
const delay = Math.random() * 4;
const duration = 3 + Math.random() * 5;
line.style.top = `${top}%`;
line.style.left = `-${width}px`;
line.style.width = `${width}px`;
line.style.animationDelay = `${-delay}s`;
line.style.animationDuration = `${duration}s`;
// 随机颜色变化
if (Math.random() > 0.7) {
line.style.background = `linear-gradient(90deg,
transparent,
var(--electric-accent),
var(--electric-primary),
transparent)`;
}
background.appendChild(line);
}
// 创建电子节点
for (let i = 0; i < 15; i++) {
const node = document.createElement('div');
node.className = 'electric-node';
// 随机位置和属性
const left = Math.random() * 100;
const top = Math.random() * 100;
const delay = Math.random() * 2;
const duration = 1 + Math.random() * 3;
node.style.left = `${left}%`;
node.style.top = `${top}%`;
node.style.animationDelay = `${-delay}s`;
node.style.animationDuration = `${duration}s`;
// 随机大小
const size = 3 + Math.random() * 6;
node.style.width = `${size}px`;
node.style.height = `${size}px`;
background.appendChild(node);
}
}
// 创建卡片电子效果
function createCardElectricEffect() {
const overlay = document.getElementById('cardElectricOverlay');
const card = document.querySelector('.card');
card.addEventListener('mouseenter', function() {
// 创建卡片电子线条
for (let i = 0; i < 8; i++) {
const line = document.createElement('div');
line.className = 'card__electric-line';
// 随机位置和方向
const isVertical = Math.random() > 0.5;
const startPos = Math.random() * 100;
const length = 20 + Math.random() * 60;
if (isVertical) {
// 垂直线条
line.style.width = '1px';
line.style.height = `${length}%`;
line.style.top = `-${length}%`;
line.style.left = `${startPos}%`;
line.style.background = `linear-gradient(180deg,
transparent,
var(--electric-secondary),
var(--electric-primary),
transparent)`;
} else {
// 水平线条
line.style.width = `${length}%`;
line.style.height = '1px';
line.style.left = `-${length}%`;
line.style.top = `${startPos}%`;
}
// 随机动画属性
const delay = Math.random() * 2;
const duration = 1 + Math.random() * 3;
line.style.animationDelay = `${-delay}s`;
line.style.animationDuration = `${duration}s`;
overlay.appendChild(line);
}
// 创建电子火花
for (let i = 0; i < 12; i++) {
const spark = document.createElement('div');
spark.className = 'card__electric-spark';
// 随机位置
const left = Math.random() * 100;
const top = Math.random() * 100;
spark.style.left = `${left}%`;
spark.style.top = `${top}%`;
// 随机动画属性
const delay = Math.random() * 1.5;
const duration = 0.5 + Math.random() * 1.5;
spark.style.animationDelay = `${-delay}s`;
spark.style.animationDuration = `${duration}s`;
// 随机颜色
if (Math.random() > 0.7) {
spark.style.backgroundColor = 'var(--electric-accent)';
spark.style.boxShadow = '0 0 6px var(--electric-accent), 0 0 10px var(--electric-primary)';
}
overlay.appendChild(spark);
}
});
card.addEventListener('mouseleave', function() {
// 清空电子效果
while (overlay.firstChild) {
overlay.removeChild(overlay.firstChild);
}
});
}
// 更新动画值(原有的函数)
function updateAnimationValues() {
const card = document.querySelector(".card");
if (!card) return;
const PX_PER_SEC = 100;
const SIZE_FACTOR = 1.4;
const { width, height } = card.getBoundingClientRect();
const filterHeight = height * SIZE_FACTOR;
const durY = filterHeight / PX_PER_SEC;
const animateDy1 = document.getElementById("animate-dy-1");
const animateDy2 = document.getElementById("animate-dy-2");
if (animateDy1) {
animateDy1.setAttribute("values", `${filterHeight}; 0`);
animateDy1.setAttribute("dur", `${durY}s`);
}
if (animateDy2) {
animateDy2.setAttribute("values", `0; -${filterHeight}`);
animateDy2.setAttribute("dur", `${durY}s`);
}
const filterWidth = width * SIZE_FACTOR;
const durX = width / PX_PER_SEC;
const animateDx1 = document.getElementById("animate-dx-1");
const animateDx2 = document.getElementById("animate-dx-2");
if (animateDx1) {
animateDx1.setAttribute("values", `${filterWidth}; 0`);
animateDx1.setAttribute("dur", `${durX}s`);
}
if (animateDx2) {
animateDx2.setAttribute("values", `0; -${filterWidth}`);
animateDx2.setAttribute("dur", `${durX}s`);
}
}
// 初始化
document.addEventListener("DOMContentLoaded", () => {
// 原有代码
const cardToObserve = document.querySelector(".card");
if (!cardToObserve) return;
const resizeObserver = new ResizeObserver(() => {
updateAnimationValues();
});
updateAnimationValues();
resizeObserver.observe(cardToObserve);
// 新添加的电子效果
createElectricBackground();
createCardElectricEffect();
// 添加点击效果
const card = document.querySelector('.card');
card.addEventListener('click', function() {
// 创建点击时的电光效果
for (let i = 0; i < 8; i++) {
const spark = document.createElement('div');
spark.className = 'card__electric-spark';
// 从中心向外扩散
const angle = Math.random() * Math.PI * 2;
const distance = 30 + Math.random() * 70;
const left = 50 + Math.cos(angle) * distance;
const top = 50 + Math.sin(angle) * distance;
spark.style.left = `${left}%`;
spark.style.top = `${top}%`;
spark.style.animationDuration = '0.5s';
spark.style.animationIterationCount = '1';
// 添加到卡片
this.querySelector('.card__electric-overlay').appendChild(spark);
// 移除元素
setTimeout(() => {
if (spark.parentNode) {
spark.parentNode.removeChild(spark);
}
}, 500);
}
});
});
</script>
</body>
</html>
御坂美琴电子特效卡片
一款基于HTML5、CSS3和JavaScript开发的御坂美琴主题电子特效卡片,具有动态电流背景和鼠标交互效果。
功能特性
🌟 视觉特效
动态电流背景:页面背景有流动的电子线条和脉动的电子节点
悬停抖动效果:鼠标悬停时卡片产生轻微抖动
边框扭曲特效:使用SVG滤镜实现边框的动态扭曲效果
电子火花效果:鼠标悬停时卡片表面出现闪烁的电子火花
点击特效:点击卡片时从中心向外扩散电子火花
多层发光效果:卡片具有多层渐变和发光层,营造立体感
🎨 设计特点
御坂美琴主题配色(蓝紫色电光色调)
响应式设计,适配各种屏幕尺寸
流畅的动画过渡效果
深色背景突出电子特效
优雅的字体和布局设计
技术实现
核心技术
HTML5:语义化结构和SVG滤镜
CSS3:动画、渐变、滤镜、自定义属性
JavaScript:动态效果生成和交互控制
SVG滤镜:实现边框扭曲效果
CSS变量:统一的配色方案管理
关键技术点
动态背景生成:使用JavaScript动态创建电子线条和节点
性能优化:使用CSS硬件加速和优化动画性能
响应式设计:基于视口和容器大小的自适应布局
交互动画:鼠标事件驱动的动态效果
文件结构
