前言
继上次实现一个旋转风车的效果后,这次我就带大家来实现一团热烈的火焰效果,用CSS
配合JS
方法来实现,十分简单,没有花里胡哨的技巧。话不多说,咱们直接进入主题。
效果预览
最终实现的相关效果如下。
CSS部分
首先我们看到CSS部分,通过样式来实现一团火焰,在CSS中创建了一个动态火焰粒子效果,使用多个半透明的圆形粒子(<span>
)通过动画模拟火焰上升消散的视觉效果。
首先是基础布局 (body
样式),相关代码如下。
body {
margin: 0;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(black, maroon); /* 黑色到深红的渐变背景 */
overflow: hidden; /* 隐藏超出部分 */
}
让页面居中,背景为黑色到深红的渐变,营造火焰的暗色环境,overflow: hidden
确保火焰粒子不会超出屏幕。
然后是火焰容器 (.flame
),相关代码如下。
.flame {
width: 10em;
height: 12em;
font-size: 24px; /* 基准单位 */
position: relative; /* 为子元素定位提供参照 */
}
火焰区域宽 10em
、高 12em
(基于 font-size: 24px
,1em = 24px
),允许子粒子绝对定位。
接着是火焰粒子 (.flame span
),相关代码如下。
.flame span {
position: absolute;
width: 5em;
height: 5em;
background: radial-gradient(
orangered 20%, /* 中心橙红色 */
rgba(255, 69, 0, 0) 70% /* 边缘透明 */
);
border-radius: 50%; /* 圆形 */
bottom: 0; /* 从底部开始 */
left: calc((var(--n) - 1) * 5em / var(--particles)); /* 水平位置 */
mix-blend-mode: screen; /* 混合模式:提亮 */
animation: rise 1s ease-in infinite; /* 上升动画 */
animation-delay: calc(var(--rnd) * 1s); /* 随机延迟 */
filter: opacity(0); /* 初始透明 */
}
粒子形状是圆形的,径向渐变从橙红(orangered
)到透明,模拟火焰发光效果。通过 CSS 变量 --n
(粒子序号)和 --particles
(总数)计算水平位置,均匀分布,并且让所有粒子从容器底部开始上升。
使用混合模式mix-blend-mode: screen
使粒子与背景混合时更亮(类似火焰叠加效果)。
然后定义了一个动画,通过 --rnd
(随机值)实现粒子错开上升,filter: opacity(0)
表示初始透明,避免突兀出现。
接着是上升动画 (@keyframes rise
),相关代码如下。
@keyframes rise {
from {
transform: translateY(0) scale(1); /* 起始位置 */
filter: opacity(0); /* 透明 */
}
25% {
filter: opacity(1); /* 完全显现 */
}
to {
transform: translateY(-10em) scale(0); /* 上升至顶部并缩小 */
filter: opacity(0); /* 淡出 */
}
}
起始时,粒子在底部,透明 (opacity(0)
),25% 时,完全显现 (opacity(1)
),结束 时,上升至顶部 (translateY(-10em)
),缩小至消失 (scale(0)
),再次透明。最终的动画效果就是粒子从底部升起、放大、再缩小淡出,模拟火焰闪烁上升。
最终效果就是多个橙红色圆形粒子从底部上升,过程中闪烁并消散,粒子位置和动画时间错开,形成自然火焰的随机感。通过简洁的 CSS 实现了复杂的粒子动画效果。
JS部分
粒子样式由 CSS 的 .flame span
控制(大小、颜色、动画等),接下来的JavaScript 则负责动态生成和定位。相关代码如下。
<script>
const COUNT_OF_PARTICLES = 100
const container = document.querySelector('.flame')
container.style.setProperty('--particles', COUNT_OF_PARTICLES)
Array(COUNT_OF_PARTICLES).fill('').forEach((particle, i) => {
let span = document.createElement('span')
span.style.setProperty('--n', i + 1)
span.style.setProperty('--rnd', Math.random())
container.appendChild(span)
})
</script>
这里动态创建了 100 个火焰粒子(<span>
元素),并将它们添加到 .flame
容器中,同时为每个粒子设置 CSS 变量以控制其位置和动画延迟。
首先通过 document.querySelector
获取 HTML 中类名为 flame
的元素(火焰的容器)。在 .flame
容器上设置 CSS 变量 --particles
,值为 100
。在 CSS 中通过 var(--particles)
计算粒子的水平位置(见上面 CSS 中的 left
属性)。
接着动态生成粒子, 创建空数组,Array(COUNT_OF_PARTICLES).fill('')
生成一个长度为 100 的数组,遍历数组,对每个元素执行回调函数,参数 i
为当前索引(从 0 开始),创建粒子:每次循环创建一个 <span>
元素。
设置 CSS 变量:
- --n
:粒子序号(i + 1
,范围 1100),用于计算水平位置。
- 1),用于动画延迟。--rnd
:随机数(Math.random()
,范围 0
最终添加到容器:将粒子 span
插入到 .flame
中。
在 CSS 中通过 calc((var(--n) - 1) * 5em / var(--particles))
计算每个粒子的 left
位置,实现水平均匀分布。例如:第一个粒子(--n: 1
)的 left
为 0
,最后一个(--n: 100
)的 left
为 4.95em
。通过 calc(var(--rnd) * 1s)
设置 animation-delay
,使粒子随机错开上升,避免同步移动。
这样处理完成后,最终效果就是100 个粒子从容器底部升起,水平均匀分布,每个粒子的上升动画有随机延迟,形成自然闪烁效果。
总结
以上就是整个效果的实现过程了,纯 CSS
实现,代码简单易懂。另外,感兴趣的小伙伴们还可以在现有基础上发散思维,比如增加点其他效果,或者更改颜色等等。关于该效果如果大家有更好的想法欢迎在评论区分享,互相学习。最后,完整代码在码上掘金里可以查看,如果有什么问题大家在评论区里讨论~