前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CSS+JS实现 | 简单的萤火虫效果

CSS+JS实现 | 简单的萤火虫效果

作者头像
jayjay
发布2022-11-02 16:56:30
9640
发布2022-11-02 16:56:30
举报
文章被收录于专栏:jay_blog

前言

夏天到了,又快到了萤火虫出来的季节了,现在的城市很少能看到漫天的萤火虫飞舞了,既然看不到,我们就用代码创造,就当骗自己一下。

代码块

https://code.juejin.cn/pen/7086277664540983299

代码实现

1.布局

布局很简单,就一个div,其他都靠js生成

代码语言:javascript
复制
<div id="app"></div>
2.闪烁效果

通过box-shadow给元素加阴影,然后使用动画改变阴影的大小和透明度来实现萤火虫的闪烁效果

代码语言:javascript
复制
    /* 萤火虫样式 */
    .round {
        width: 10px;
        height: 10px;
        background-image: radial-gradient(rgba(255, 255, 199, 1), rgba(203, 255, 138, 0.8), rgba(105, 193, 114, 0.8));
        border-radius: 50%;
        animation: shadow 2s infinite;
    }

    /* 闪烁动画 */
    @keyframes shadow {
        0% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0);
        }

        10% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0.2);
        }

        20% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0.4);
        }

        30% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0.6);
        }

        40% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0.8);
        }

        50% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 1);
        }

        60% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0.8);
        }

        70% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0.6);
        }

        80% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0.4);
        }

        90% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0.2);
        }

        100% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0);
        }
    }

效果如图:

ScreenRecorderProject3.gif
ScreenRecorderProject3.gif

因为萤火虫的光大小不一致,然后我们实现几个不同的大小的样式,最终CSS样式如下:

代码语言:javascript
复制
 html {
        background-color: black; overflow-x: hidden; overflow-y: hidden; }
#app {
        width: 100%;
        height: 100vh;
    }

    .round {
        width: 10px;
        height: 10px;
        background-image: radial-gradient(rgba(255, 255, 199, 1), rgba(203, 255, 138, 0.8), rgba(105, 193, 114, 0.8));
        border-radius: 50%;
        animation: shadow 2s infinite;
        transition-property: left, top;
        transition-duration: 1s, 1s;
        transition-timing-function: ease,ease;
    }

    .round2 {
        width: 8px;
        height: 8px;
        background-image: radial-gradient(rgba(255, 255, 199, 1), rgba(203, 255, 138, 0.8), rgba(105, 193, 114, 0.8));
        border-radius: 50%;
        animation: shadow2 2s infinite;
        transition-property: left, top;
        transition-duration: 1s, 1s;
        transition-timing-function: ease,ease;
    }

    .round3 {
        width: 5px;
        height: 5px;
        background-image: radial-gradient(rgba(255, 255, 199, 1), rgba(203, 255, 138, 0.8), rgba(105, 193, 114, 0.8));
        border-radius: 50%;
        animation: shadow2 2s infinite;
        transition-property: left, top;
        transition-duration: 1s, 1s;
        transition-timing-function: ease,ease;
    }

    @keyframes shadow {
        0% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0);
        }

        10% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0.2);
        }

        20% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0.4);
        }

        30% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0.6);
        }

        40% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0.8);
        }

        50% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 1);
        }

        60% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0.8);
        }

        70% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0.6);
        }

        80% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0.4);
        }

        90% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0.2);
        }

        100% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0);
        }
    }


    @keyframes shadow2 {
        0% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0);
        }

        10% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0.2);
        }

        20% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0.4);
        }

        30% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0.6);
        }

        40% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0.8);
        }

        50% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 1);
        }

        60% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0.8);
        }

        70% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0.6);
        }

        80% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0.4);
        }

        90% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0.2);
        }

        100% {

            box-shadow: 0px 0px 5px 5px rgba(105, 193, 114, 0);
        }
    }
3.动态生成萤火虫

生成元素比较简单,直接只用js的document.createElement方法即可实现,随机分配不同大小的class给元素,然后随机指定坐标生成,给父元素添加子节点,并添加到一个数组中方便后面批量运动

代码语言:javascript
复制
    let arr = [];
    let app = document.getElementById("app")
    let clientW = app.offsetWidth;
    let clientH = app.offsetHeight;
    function addItem() {
        let div = document.createElement("div");
        const cName = (Math.floor(Math.random() * 3) + 1);
        div.setAttribute("class", "round" + (cName == 0 ? '' : cName));
        div.style.position = 'absolute';
        div.style.left = Math.floor(Math.random() * clientW) + "px";
        div.style.top = Math.floor(Math.random() * clientH) + "px";
        app.appendChild(div);
        arr.push(div);
    }

萤火虫肯定不是静止不动,会飞舞,所以我们要给元素添加移动的动画,实现思路是动态修改萤火虫元素lef top 属性的值,当然这个数值是随机,且不能为正数,要有正负数才行,不然只会往一个方向移动

代码语言:javascript
复制
    function move() {
        //防止页面卡顿,如果有1000个元素就停止生成
        if(arr.length > 1000) {
            clearInterval(window.addTask);
        }
        if (arr.length > 0) {
            arr.forEach(div => {
                let speed = Math.floor(Math.random() * clientW/20) + 10;//定义总体速度
                let left = div.offsetLeft;
                let top = div.offsetTop;
                //随机设置在x和y方向的速度
                let theta = Math.floor(Math.random() * speed) + 10 * Math.PI * Math.random();
                let speedX = Math.floor(speed * Math.cos(theta));
                let speedY = Math.floor(speed * Math.sin(theta));
                left += speedX;
                top += speedY;
                div.style.left = left + "px"
                div.style.top = top + "px"
            })
        }
    }

最后只要启动两个定时器即可运行

代码语言:javascript
复制
window.addTask = setInterval(addItem, 200)
setInterval(move, 500)
ScreenRecorderProject3_1.gif
ScreenRecorderProject3_1.gif

结语

飞舞的轨迹实现效果不是很完美,就先这样吧,我本是爱摸鱼的后端,就当图个一乐,顺便体验下掘金的代码块。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-04-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 代码块
  • 代码实现
    • 1.布局
      • 2.闪烁效果
        • 3.动态生成萤火虫
        • 结语
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档