JS烟花案例

Posted 小小荧

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JS烟花案例相关的知识,希望对你有一定的参考价值。

技术图片

html代码部分

<!DOCTYPE html>
<!--
 * @Descripttion: 
 * @version: 
 * @Author: 小小荧
 * @Date: 2020-03-18 19:15:15
 * @LastEditors: 小小荧
 * @LastEditTime: 2020-03-18 20:14:28
 -->
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        .container {
            width: 80%;
            height: 600px;
            border: 2px solid red;
            background: #000;
            margin: 20px auto;
            cursor: pointer;
            position: relative;
            left: 0;
            top: 0;
            overflow: hidden;
        }

        .fire {
            width: 10px;
            height: 10px;
            position: absolute;
            bottom: 0;
        }
    </style>
</head>

<body>
    <div class="container"></div>
    <script src="./js/animate.js"></script>
    <script src="./js/utils.js"></script>
    <script src="./js/index.js"></script>
    <script>
        let container_ele = document.querySelector(".container");
        container_ele.addEventListener("click", function(evt){
            var e = evt || event;
            new FireWork(e.offsetX, e.offsetY, ".container");
        })
    </script>
</body>

</html>

JS代码运动函数

/*
 * @Descripttion: 
 * @version: 
 * @Author: 小小荧
 * @Date: 2020-03-17 18:01:21
 * @LastEditors: 小小荧
 * @LastEditTime: 2020-03-18 19:14:55
 */
/**
 * 多属性的动画函数
 * @param {*} ele 需要运动的节点
 * @param {*} attr_options 传入的是一个需要运动的属性包括运动的目标值,操作的节点属性 
 * @param {*} timefn 运动的形式,默认是缓冲运动
 * @param {*} speed  运动的速度
 */
function animate(ele, attr_options, callback, timefn = "swing", speed = 5) {

    // 我们需要把传入的options处理成
    /* 
        {“width : {
            target : 200,
            iNow : 100
        }}这个形式
    */

    for (var attr in attr_options) {
        attr_options[attr] = {
            target: attr === "opacity" ? parseInt(attr_options[attr] * 100) : attr_options[attr],
            // 需要计算得到
            iNow: attr === "opacity" ? parseInt(getComputedStyle(ele)[attr] * 100) : parseInt(getComputedStyle(ele)[attr])
        }
    }

    //    为了防止每个节点的定时器冲突,每次进入的时候我们需要先清理下节点的定时器
    clearInterval(ele.timer);
    //    然后再去设置定时器
    ele.timer = setInterval(function () {

        // 因为是多属性运动,我们首先循环遍历每一个属性
        for (var attr in attr_options) {

            var target = attr_options[attr].target;

            var iNow = attr_options[attr].iNow;

            // 计算speed 判断是不是缓冲运动
            if (timefn === "swing") {
                speed = (target - iNow) / 20;
                // 为了防止速度无法达到一个整数
                speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
            }
            // 判断是不是匀速运动
            else if (timefn === "liner") {
                speed = attr_options[attr].iNow < attr_options[attr].target ? Math.abs(speed) : -Math.abs(speed);
            }

            // 运动之中条件的判断
            if (Math.abs(target - iNow) <= Math.abs(speed)) {

                if (attr === "opacity") {
                    ele.style[attr] = target / 100;
                } else {

                    ele.style[attr] = target + "px";

                }

                // 每次一个属性运动完成之后我们就直接将它删除
                delete attr_options[attr];

                // 每次都去循环看一下还有没有属性需要操作
                for (var num in attr_options) {
                    return false;
                }
                // 清理定时器 因为我们是一个定时器绑定多个属性操作所以我们需要保证所有的属性都完成之后我们才可以将定时器清除
                clearInterval(ele.timer);
                // 等结束之后我们需要判断这个回到函数是函数我们就回调
                typeof callback === "function" ? callback() : ""

            } else {
                attr_options[attr].iNow += speed;
                if (attr === "opacity") {
                    ele.style[attr] = attr_options[attr].iNow / 100;
                } else {
                    ele.style[attr] = attr_options[attr].iNow + "px";
                }
            }
        }


    }, 30);
}

JS代码核心主业务代码

/*
 * @Descripttion: 
 * @version: 
 * @Author: 小小荧
 * @Date: 2020-03-18 19:16:48
 * @LastEditors: 小小荧
 * @LastEditTime: 2020-03-18 20:12:07
 */
class FireWork {
    // 构造器
    /**
     * 
     * @param {*} x x轴坐标
     * @param {*} y y轴坐标
     * @param {*} seletor 选择器名
     */
    constructor(x, y, seletor) {
        // 父容器的节点
        this.main = document.querySelector(seletor);

        this.init(x, y);
    }

    /**
     * 初始化方法
     * @param {*} x x的坐标 
     * @param {*} y y的坐标
     */
    init(x, y) {

        this.x = x;
        this.y = y;

        // 创建的烟花的节点
        this.ele = this.createFireWorkEle();
        // 运动的最大left值
        this.left_max = this.main.offsetWidth - this.ele.offsetWidth;
        // 运动的最大的top值
        this.top_max = this.main.offsetHeight - this.ele.offsetHeight;

        // 设置烟花的开始颜色
        this.randomColor(this.ele);
        // 烟花开始运动
        this.fireworkUp(this.ele);
    }
    /**
     * 创建烟花的元素
     */
    createFireWorkEle() {
        // 创建节点
        let ele = document.createElement("div");
        // 设置类名
        ele.className = "fire";
        // 在父容器追加节点
        this.main.appendChild(ele);
        return ele;
    }

    /**
     * 
     * 烟花运动的方法
     * @param {*} ele 运动的这个烟花
     */
    fireworkUp(ele) {

        // 设置left
        ele.style.left = this.x + "px";
        // 烟花向上的运动我们使用animate动画
        animate(ele, {
            top: this.y,
        }, () => {

            // 等到这个烟花运动结束之后呢我们需要将这个烟花给删除了
            ele.parentNode.removeChild(ele);
            // 结束之后烟花开始爆炸
            this.fireworkBlast();

        });

    }

    /**
     * 烟花爆炸的方法
     */
    fireworkBlast() {
        // 我们设置爆炸的数量为20
        for (let i = 0; i < 20; i++) {
            // 我们需要重新创建烟花的元素
            let ele = this.createFireWorkEle();
            // 给元素设置随机背景颜色和left,top,圆角属性值
            this.randomColor(ele);

            ele.style.left = this.x + "px";

            ele.style.top = this.y + "px";

            ele.style.borderRadius = "50%";

            // 然后我们需要让这些元素开始运动,先获取随机坐标带你
            animate(ele, this.randomPos(), () => {
                // 删除烟花
                ele.parentNode.removeChild(ele)
            });
        }
    }

    /**
     * 随机获取坐标点
     */
    randomPos() {
        return {
            left: Math.round(Math.random() * this.left_max),
            top: Math.round(Math.random() * this.top_max)
        }
    }

    /**
     * 
     * 随机背景颜色
     * @param {*} ele 小烟花的元素
     */
    randomColor(ele) {

        return ele.style.backgroundColor = utils.randomColor();
    }

}

utils的随机生成颜色的函数

 let randomColor = function () {
        let res = "#";
        for (let i = 0; i < 6; i++) {
            res += parseInt(Math.random() * 10).toString(16);
        }
        return res;
    }

以上是关于JS烟花案例的主要内容,如果未能解决你的问题,请参考以下文章

烟花代码,予心上人最璀璨烟花—— 附源码与成品(HTML+CSS+JS)

Js烟花代码分享

Js烟花代码分享

JavaScript中的面向对象编程,详解原型对象及prototype,constructor,proto,内含面向对象编程详细案例(烟花案例)

机器学习实战应用案例100篇(十七)-烟花算法从原理到实战应用

机器学习实战应用案例100篇(十七)-烟花算法从原理到实战应用