呼吸灯这个效果在很多网页里都能见到——加载状态、消息通知、氛围装饰一颗发光的圆点慢慢变亮又慢慢变暗节奏和人的呼吸很像。用HTML实现“智能呼吸灯”本质上就是用一个DOM元素、一段CSS动画、再加一点JavaScript交互把这个自然节奏复刻到浏览器里。这篇文章不说虚的直接从一个可运行的小项目出发把实现原理、参数设计、常见坑一次讲透。刚学完HTML/CSS基础想练手的前端新人可以照着敲一遍需要做提示灯、加载反馈、页面氛围效果的老手也可以把代码直接抄走。1. 呼吸灯的“呼吸”到底是什么意思1.1 效果拆解一个周期里发生了什么呼吸灯不是简单的“亮—灭”闪烁而是一连串连续的亮度变化。一个完整周期通常包含三个阶段从暗慢慢亮起到达峰值后保持极短的一瞬间再缓缓暗下来回到起点。对应到网页里的视觉参数上透明度opacity从0.2升到1再平滑回落到0.2元素尺寸transform: scale从0.9放大到1.1再缩回如果还想做得更有氛围可以用box-shadow模拟一圈光晕。这三个维度缺一个都觉得“不像”。只做透明度灯像在空气中淡入淡出但少了“呼吸时身体微微起伏”的感觉只做缩放又像一个气球在吹气没有光线变化。真正像呼吸的组合是放大和变亮同时发生缩小和变暗同时发生光晕跟着扩散和收缩。这样看起来就是一颗有生命的灯珠而不是一个会闪的圆点。1.2 周期和节奏怎么定成年人平静呼吸的频率大约是每分钟12到20次也就是单次呼吸3到5秒。网页里的呼吸灯不需要严格对标人体但节奏感非常重要。周期太长超过6秒用户会以为页面卡住了周期太短低于1秒又变成了急促的闪烁给人紧张感和“呼吸”两个字就没什么关系了。我实际做下来比较舒服的区间是3秒到4秒。具体分法是亮起过程占40%暗下过程占40%中间峰值停顿占20%左右。这个比例模拟的是正常呼吸——吸气之后有一个短暂的屏息而不是刚到最亮就立刻回落。通过keyframes的百分比控制你能精确还原这套节奏这也是CSS动画比JS逐帧改透明度更优雅的原因之一。1.3 技术选型CSS动画还是JS定时器很多人都踩过这个坑一上来就用JavaScript写一个setInterval每几十毫秒去改一次元素的透明度。这样能不能实现能。但你要清楚JavaScript跑在浏览器主线程上页面只要有其他任务——滚动监听、布局计算、图片加载、接口返回后的DOM更新——透明度更新就可能会被插队动画就变成一卡一卡的。浏览器对CSS动画做了专门优化transform、opacity这类属性走的是合成器线程不占用主线程所以能用CSS动画解决的就不要用JS去逐帧改。那需要交互怎么办本次项目的思路是“CSS动画负责动JS负责指挥”——用CSS变量把动画时长、颜色、亮度这些可调参数暴露出来JS只修改变量不直接改每一帧的样式。这样既保住了性能又实现了“智能”控制。2. 基础版纯CSS让灯“亮起来再暗下去”2.1 搭建HTML结构呼吸灯需要一个载体。最简单的结构就是一个div给它一个类名然后全交给CSS处理。!DOCTYPE html html langzh-cn head meta charsetutf-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 title智能呼吸灯 - 基础版/title style /* 样式稍后放入 */ /style /head body div classbreath-light/div /body /html这里有个容易被忽略的点div默认是块级元素宽高在没有内容的时候是0直接写样式是看不见灯的。所以第一步是给这个div一个明确的width和height再用border-radius: 50%把它变成圆形。至于摆放位置可以让它居中也可以放在页面的某个角落当指示灯取决于你的使用场景。2.2 用keyframes定义呼吸动画呼吸动画的核心在keyframes。我们需要定义三个关键帧起点暗态、中点亮态、终点回到暗态。.breath-light { width: 120px; height: 120px; border-radius: 50%; background: radial-gradient(circle, rgba(255,255,255,0.95), rgba(0,150,255,0.6)); /* 初始状态和动画第一帧保持一致避免闪烁 */ opacity: 0.25; transform: scale(0.9); animation: breathe 3s ease-in-out infinite; } keyframes breathe { 0% { opacity: 0.25; transform: scale(0.9); box-shadow: 0 0 10px 2px rgba(0,150,255,0.2); } 40% { opacity: 1; transform: scale(1.1); box-shadow: 0 0 40px 15px rgba(0,150,255,0.7); } 60% { opacity: 1; transform: scale(1.1); box-shadow: 0 0 40px 15px rgba(0,150,255,0.7); } 100% { opacity: 0.25; transform: scale(0.9); box-shadow: 0 0 10px 2px rgba(0,150,255,0.2); } }animation这行是重点breathe是动画名称3s是单次周期时长ease-in-out是缓动函数infinite是无限循环。ease-in-out的意思是动画在起始和结束阶段速度慢、中段速度快恰好对应呼吸“缓缓开始、缓缓结束”的自然状态。40%和60%处各停一下模拟屏息瞬间。这样一条简单的动画已经能看出呼吸感了。2.3 让“光晕”更真实呼吸灯之所以比普通圆点好看核心在光晕。光晕用两层实现第一层是background上用radial-gradient径向渐变做一个从中心亮到边缘暗的灯珠效果第二层是box-shadow向外扩散的辉光。radial-gradient的参数要理解circle表示圆形渐变第一个颜色是中心颜色第二层是边缘颜色。如果你希望灯珠更接近真实LED中心用接近白色的浅蓝边缘用纯蓝色模拟出“灯珠内部更亮”的视觉感受。box-shadow这个属性值得多花点时间调。它有两个模糊半径参数第一个是模糊距离第二个是扩散距离。我做呼吸灯时的经验是“0 0 40px 15px”这种组合在深色背景上效果最好光晕均匀且不刺眼如果是浅色页面阴影的rgba透明度要降到0.3以下否则会显得页面脏。提示别把box-shadow的模糊半径堆到100px以上。视觉上虽然更夸张但浏览器绘制模糊阴影的计算量会明显增加动起来容易掉帧。3. 进阶版让灯“聪明”起来3.1 点击暂停与启动一盏只会循环的灯其实不算“智能”。第一步要让它听从指挥点击一下暂停再点击继续。CSS里有一个专门干这事的属性——animation-play-state取值paused时动画冻结取值running时继续播放。const light document.querySelector(.breath-light); const toggleBtn document.getElementById(toggleBtn); let isRunning true; toggleBtn.addEventListener(click, () { isRunning !isRunning; light.style.animationPlayState isRunning ? running : paused; toggleBtn.textContent isRunning ? 暂停 : 启动; });需要说明的是animation-play-state在切换时不会从头播放而是保持在当前帧继续。也就是说点击暂停后灯会停在那一刻的亮暗状态再点击启动时从停住的位置继续呼吸这正好符合智能设备的直觉操作。3.2 用CSS变量实现速度调节想动态调整呼吸快慢最直接的办法是用JavaScript修改animation-duration。但如果光只改这一项动画会“跳”一下——因为浏览器需要重新计算动画周期。更平滑的做法是把动画时长定义为CSS变量JS只需要改变量值。.breath-light { --breath-duration: 3s; animation: breathe var(--breath-duration) ease-in-out infinite; }const speedSlider document.getElementById(speedSlider); speedSlider.addEventListener(input, () { light.style.setProperty(--breath-duration, speedSlider.value s); });CSS变量的好处是修改它的值不会打断动画浏览器会在下一个渲染帧自动调整动画时长。用户拖动滑块时灯会从当前状态直接进入新的节奏体验非常顺滑。这个模式是“CSS动画 JS指挥”的核心后续所有动态参数都可以照这个套路来做。3.3 颜色切换与亮度控制呼吸灯不能只有蓝色一种。我们可以把发光颜色也变成CSS变量然后用一组色块让用户切换。这里有一点要特别注意box-shadow不支持直接写“rgba(var(--color), 0.6)”但可以在变量里存“0, 150, 255”这种RGB分量然后配合rgba()函数使用。.breath-light { --glow-rgb: 0, 150, 255; background: radial-gradient(circle, rgba(255,255,255,0.95), rgba(var(--glow-rgb), 0.6)); } keyframes breathe { 0% { opacity: 0.25; transform: scale(0.9); box-shadow: 0 0 10px 2px rgba(var(--glow-rgb), 0.2); } 40% { opacity: 1; transform: scale(1.1); box-shadow: 0 0 40px 15px rgba(var(--glow-rgb), 0.7); } 100% { opacity: 0.25; transform: scale(0.9); box-shadow: 0 0 10px 2px rgba(var(--glow-rgb), 0.2); } }切换颜色时JS只改一个变量function setColor(rgbString) { light.style.setProperty(--glow-rgb, rgbString); }亮度控制则可以再引入一个变量比如--max-opacity然后在动画的最亮帧使用var(--max-opacity)。调暗灯光时把值从1改成0.7灯就“收着亮”不会破坏动画的节奏。3.4 一键模拟“睡眠呼吸”模式做这个项目时我发现一个好玩的需求很多人想要一个“睡眠模式”让灯的呼吸节奏变得更慢、更柔和用来当夜灯或者专注时钟。实现方式是把时长变长、透明度上限压低、光晕缩小同时切换背景色为暖黄色。这其实就是把上面几个变量组合一下做一个预设按钮function sleepMode() { light.style.setProperty(--breath-duration, 6s); light.style.setProperty(--glow-rgb, 255, 180, 60); light.style.setProperty(--max-opacity, 0.7); }“智能”就体现在这里不是一条动画走到底而是把参数组合成可切换的模式用户能根据场景一键切换。这个思路放到真实项目里就是一个完整的主题化交互组件了。4. 完整可运行Demo智能呼吸灯.html4.1 完整代码把上面的能力整合到一起做一个带控制面板的完整页面。控制面板包含暂停/启动按钮、速度滑块、四个颜色选项、睡眠模式按钮。全部代码只有一个HTML文件复制到本地就能跑没有任何依赖。!DOCTYPE html html langzh-cn head meta charsetutf-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 title智能呼吸灯/title style * { margin: 0; padding: 0; box-sizing: border-box; } body { min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; background: #0f172a; font-family: Arial, sans-serif; -webkit-tap-highlight-color: transparent; } .stage { display: flex; align-items: center; justify-content: center; width: 100%; height: 320px; } .breath-light { width: 120px; height: 120px; border-radius: 50%; background: radial-gradient(circle, rgba(255,255,255,0.95), rgba(var(--glow-rgb), 0.6)); box-shadow: 0 0 10px 2px rgba(var(--glow-rgb), 0.2); opacity: 0.25; transform: scale(0.9); animation: breathe var(--breath-duration) ease-in-out infinite; transition: box-shadow 0.3s ease; } keyframes breathe { 0% { opacity: 0.25; transform: scale(0.9); box-shadow: 0 0 10px 2px rgba(var(--glow-rgb), 0.2); } 40% { opacity: var(--max-opacity, 1); transform: scale(1.1); box-shadow: 0 0 40px 15px rgba(var(--glow-rgb), 0.7); } 60% { opacity: var(--max-opacity, 1); transform: scale(1.1); box-shadow: 0 0 40px 15px rgba(var(--glow-rgb), 0.7); } 100% { opacity: 0.25; transform: scale(0.9); box-shadow: 0 0 10px 2px rgba(var(--glow-rgb), 0.2); } } .controls { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; justify-content: center; padding: 16px 20px; background: rgba(255,255,255,0.06); border-radius: 16px; max-width: 440px; margin: 0 16px; } .controls button { border: none; padding: 10px 18px; border-radius: 10px; background: #3b82f6; color: #fff; font-size: 14px; cursor: pointer; } .controls button:hover { background: #2563eb; } .controls input[typerange] { flex: 1; min-width: 140px; } .color-dots { display: flex; gap: 8px; } .color-dots span { width: 24px; height: 24px; border-radius: 50%; cursor: pointer; border: 2px solid rgba(255,255,255,0.3); } .color-dots span.active { border-color: #fff; } /style /head body div classstage div classbreath-light idlight/div /div div classcontrols button idtoggleBtn暂停/button input typerange idspeedSlider min2 max6 step0.5 value3 title呼吸速度 div classcolor-dots span>
企业数字化 ERP 产品动态
相关推荐
小米手机传输文件到电脑的7种方法:有线无线云备份全攻略 手机里的照片、视频、微信文件、录音、下载的文档,攒上一年半载,容量告急几乎是必然。尤其是用小米手机的朋友,MIUI 和澎湃 OS 的相机素质不差,随手一拍就是几 MB 起步,4K 视频更是几十秒就上百 MB,再加上微… · 2026/9/26 11:59:45
纯前端导航页开发实战:AI辅助与Yandex聚合入口设计 1. 这个导航页到底解决什么问题先说说我为什么要折腾这个东西。日常工作中我经常需要在不同设备、不同浏览器之间切换,每次换环境都要重新翻收藏夹、重新登录各种账号,时间全耗在“找入口”这件事上了。尤其是帮同事临时查个资料、给朋友演示个工具&… · 2026/9/26 11:59:45
YOLOv8课堂学生行为检测实战:从数据标注到部署 简介:基于YOLOv8的课堂学生行为检测系统是一份面向课程设计、毕业设计与深度学习入门实践的高完整性项目包,适合计算机相关专业学生、高校教师及开发者开展课堂场景下学生姿态、抬头/低头、玩手机等行为识别实验。项目难度适中,源码、配置与说… · 2026/9/26 11:59:33
从0到1搭建AI Agent平台:造同事思维与落地方案 1. “造同事”这件事,第一步不是选框架,而是换思维1.1 同事和工具的本质区别我看到这个标题的第一反应,不是“又有人来蹭 Agent 热点了”,而是觉得“造同事”这三个字,其实把 AI Agent 这件事说透了。过去我们做软件&a… · 2026/9/26 12:31:22
企业级万兆网卡选型避坑指南:物理层、链路层与系统集成三大维度 1. 为什么“万兆网卡”四个字背后藏着三道采购雷区最近帮一家做视频渲染的客户选网卡,他们预算充足,直接甩出一句:“上万兆的,越贵越好。”结果我翻完他们采购清单才发现,三张标着“10Gbps”的网卡,一张是P… · 2026/9/26 12:31:22
AI 终端一键修复在线业务故障(以OpenClaw为例):TaoToken 统一 Key 配置与验证 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 12:31:16
SAP OData服务实战:从SEGW到RAP,搞定建服务、权限与调试 我最近几乎每周都要回答几遍同样的问题:SAP OData服务到底怎么建?为什么 SEGW 里明明激活了,前端还是调不通?RAP 里的 OData 和以前那套有什么区别?这些问题问得很有代表性,因为 SAP OData 已经不是 ABAP 开… · 2026/9/26 12:31:16
Cursor、Copilot与Claude Dev:AI编程工具选型指南与实战对比 最近后台和群里被问得最多的一个问题:Cursor、GitHub Copilot、Claude Dev,到底选哪个?这事其实挺挑人的,因为这三兄弟根本不是一码事——有人拿它们比较谁更强,但我觉得更准确的说法是,它们各自代表的是一… · 2026/9/26 12:31:16
联通光猫超级密码获取与桥接设置全指南 1. 项目概述:为什么普通用户需要光猫超级密码?联通光猫不是普通路由器,它是一台被运营商深度定制、层层加锁的“网络门禁系统”。你拿到手的那台中兴F601、华为HS8145V、烽火HG680-J或创维E900V22D,表面看是Wi-Fi发射器࿰… · 2026/9/26 12:31:16
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍 简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践 一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46