一个可以互动的开/关灯源代码

探索一个前端小案例,通过CSS动画和JavaScript实现明亮模式和黑暗模式切换的按钮效果,适合作为动画和交互的练习项目。
直达下载
回到上一页
clickgpt_line.png_noView
介绍

今天我来给大家分享一个有趣的前端小案例,先给大家描述一下效果吧:点击按钮后,页面会在“明亮模式”和“黑暗模式”之间切换。按钮本身是一个模拟插头插座的SVG图像,点击时插头会有个轻微的旋转动画,仿佛真的是在插电源似的。

web_effect_turn_off_lights_1

是不是很有趣?这种效果看起来简单,但实现起来却非常精妙,包含了一些值得细细研究的前端技术点。下面我们就一起拆解一下这个小案例,看看它是如何一步步实现的。

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

这里有几点需要注意:

  1. CSS变量--hue是主色调,通过它可以方便地调节整个页面的配色,类似于主题切换的效果。通过hsl()函数配合变量使用,可以非常灵活地管理颜色。
  2. 响应式字体大小:使用calc()函数结合vwpx单位,实现了字体大小随着视口宽度的变化而动态调整。这种方式不仅可以在各种设备上获得良好的显示效果,还能减少为不同屏幕设备设计的工作量。
  3. 过渡效果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代码也非常简洁:

  1. 事件监听器DOMContentLoaded事件确保在整个DOM加载完毕后,才执行代码。这是为了确保页面的元素都可以被正确获取到。
  2. Plugs类:这个类的构造函数接受一个按钮的选择器(即buttonEl),并为按钮绑定了一个点击事件,事件的处理函数就是toggleTheme
  3. 主题切换逻辑:在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属性结合translaterotate来模拟插头的插入和拔出。不同的SVG片段会绑定不同的动画,从而组合出一个流畅的动作效果。

结语

这个“开灯关灯”小案例通过简洁的HTML结构、灵活的CSS动画和少量JavaScript逻辑,巧妙地实现了灯光的开关效果。

  • CSS动画:核心是通过CSS动画完成插头的插入拔出效果,这部分的关键在于对动画时间轴的精准控制,模拟出一个真实的开关过程。
  • JavaScript交互:JavaScript部分相对简单,但它是整个效果的驱动器。通过监听事件来切换状态,并动态修改属性,达到页面主题切换的效果。

我觉得,这个小项目很适合作为前端动画和交互的练习案例,既锻炼了对CSS动画的理解,又强化了DOM操作和事件处理的能力。

编程学习
编程学习 免费领取编程学习资料 进编程学习交流群
订阅号
视频号
公众号 关注公众号,回复关键字java领取大厂最新面试题
×
编程学习
免费领取编程学习资料 进编程学习交流群