一个可以互动的开/关灯源代码
探索一个前端小案例,通过CSS动画和JavaScript实现明亮模式和黑暗模式切换的按钮效果,适合作为动画和交互的练习项目。
直达下载
回到上一页 介绍
今天我来给大家分享一个有趣的前端小案例,先给大家描述一下效果吧:点击按钮后,页面会在“明亮模式”和“黑暗模式”之间切换。按钮本身是一个模拟插头插座的SVG图像,点击时插头会有个轻微的旋转动画,仿佛真的是在插电源似的。
是不是很有趣?这种效果看起来简单,但实现起来却非常精妙,包含了一些值得细细研究的前端技术点。下面我们就一起拆解一下这个小案例,看看它是如何一步步实现的。
HTML结构分析
首先,来看一下HTML结构:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>开灯!关灯!</title>
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<style>
/* 这里会放置我们的CSS样式 */
</style>
</head>
<body>
<button class="plugs" type="button">
<svg class="plugs__img" viewBox="0 0 70 35" width="700px" height="350px" aria-hidden="true">
<!-- 这里是SVG图像的内容 -->
</svg>
<span class="plugs__label">Power</span>
</button>
<script>
// 这里会放置我们的JavaScript代码
</script>
</body>
</html>
这是一个非常简洁的HTML结构,主体部分就是一个<button>
元素,内含一个SVG图像和一个隐藏的文本标签。为了视觉效果,SVG图像被用作按钮的显示内容,<span>
标签则用于辅助屏幕阅读器识别。
CSS:动画与样式的核心
接下来,我们来看CSS部分。这段代码里大量使用了CSS变量和动画。先看看一些关键的CSS部分:
:root {
--hue: 223;
--bg: hsl(var(--hue), 10%, 10%);
--fg: hsl(var(--hue), 10%, 90%);
--primary: hsl(var(--hue), 90%, 50%);
--trans-dur: 0.3s;
--trans-timing: cubic-bezier(0.65, 0, 0.35, 1);
font-size: calc(14px + (70 - 14) * (100vw - 280px) / (3840 - 280));
}
body, button {
color: var(--fg);
font: 1em/1.5 sans-serif;
transition: background-color calc(var(--trans-dur) * 0.5) steps(1, end), color calc(var(--trans-dur) * 0.5) steps(1, end);
}
body {
background-color: var(--bg);
display: flex;
height: 100vh;
}
button.plugs {
background-color: transparent;
cursor: pointer;
margin: auto;
outline: none;
}
这里有几点需要注意:
- CSS变量:
--hue
是主色调,通过它可以方便地调节整个页面的配色,类似于主题切换的效果。通过hsl()
函数配合变量使用,可以非常灵活地管理颜色。 - 响应式字体大小:使用
calc()
函数结合vw
和px
单位,实现了字体大小随着视口宽度的变化而动态调整。这种方式不仅可以在各种设备上获得良好的显示效果,还能减少为不同屏幕设备设计的工作量。 - 过渡效果:
transition
属性设置了颜色变化的过渡效果,使用了steps
函数,使颜色变化显得更为“机械”或“分步”,这在某些视觉效果中非常有用。
JavaScript:小而巧的交互逻辑
CSS虽然负责了大部分的视觉效果,但交互逻辑离不开JavaScript的帮助。来看一下JavaScript部分:
'use strict';
window.addEventListener('DOMContentLoaded', () => {
const plugs = new Plugs('button');
});
class Plugs {
constructor(buttonEl) {
this.button = document.querySelector(buttonEl);
this.button.addEventListener('click', this.toggleTheme.bind(this));
}
toggleTheme() {
const pressed = this.button.getAttribute('aria-pressed') === 'true';
this.button.setAttribute('aria-pressed', `${!pressed}`);
document.documentElement.setAttribute('data-dark', `${pressed}`);
}
}
这个JavaScript代码也非常简洁:
- 事件监听器:
DOMContentLoaded
事件确保在整个DOM加载完毕后,才执行代码。这是为了确保页面的元素都可以被正确获取到。 - Plugs类:这个类的构造函数接受一个按钮的选择器(即
buttonEl
),并为按钮绑定了一个点击事件,事件的处理函数就是toggleTheme
。 - 主题切换逻辑:在
toggleTheme
方法中,通过aria-pressed
属性判断当前的状态是开还是关,然后反转这个状态并切换整个页面的主题(通过data-dark
属性)。
SVG动画:让按钮“动”起来
SVG部分是这个按钮最亮眼的地方,给你一种插电源的感觉。这部分的核心是CSS动画的应用。举个简单的例子:
@keyframes left-swing-tail-on {
from { transform: translate(13px,10px) rotate(0); }
50% { transform: translate(13px,10px) rotate(-32deg); }
to { transform: translate(13px,10px) rotate(-90deg); }
}
这个动画实现了插头的旋转效果,通过transform
属性结合translate
和rotate
来模拟插头的插入和拔出。不同的SVG片段会绑定不同的动画,从而组合出一个流畅的动作效果。
结语
这个“开灯关灯”小案例通过简洁的HTML结构、灵活的CSS动画和少量JavaScript逻辑,巧妙地实现了灯光的开关效果。
- CSS动画:核心是通过CSS动画完成插头的插入拔出效果,这部分的关键在于对动画时间轴的精准控制,模拟出一个真实的开关过程。
- JavaScript交互:JavaScript部分相对简单,但它是整个效果的驱动器。通过监听事件来切换状态,并动态修改属性,达到页面主题切换的效果。
我觉得,这个小项目很适合作为前端动画和交互的练习案例,既锻炼了对CSS动画的理解,又强化了DOM操作和事件处理的能力。
×
直达下载