使用面向对象写一个烟花效果

面向对象(OOP)理解:

Object Oriented Programming,原来就是面向对象的编程啊,还有OOD(面向对象的设计),OOA(面向对象的分析)。那什么是面向对象呢?

举个最简单点的例子来区分 面向过程和面向对象

有一天你想吃鱼香肉丝了,怎么办呢?你有两个选择

1、自己买材料,肉,鱼香肉丝调料,蒜苔,胡萝卜等等然后切菜切肉,开炒,盛到盘子里。

2、去饭店,张开嘴:老板!来一份鱼香肉丝!

看出来区别了吗?这就是1是面向过程,2是面向对象。

面向对象有什么优势呢?首先你不需要知道鱼香肉丝是怎么做的,降低了耦合性。如果你突然不想吃鱼香肉丝了,想吃洛阳白菜,对于1你可能不太容易了,还需要重新买菜,买调料什么的。对于2,太容易了,大喊:老板!那个鱼香肉丝换成洛阳白菜吧,提高了可维护性。总的来说就是降低耦合,提高维护性!

面向过程是具体化的,流程化的,解决一个问题,你需要一步一步的分析,一步一步的实现。

面向对象是模型化的,你只需抽象出一个类,这是一个封闭的盒子,在这里你拥有数据也拥有解决问题的方法。需要什么功能直接使用就可以了,不必去一步一步的实现,至于这个功能是如何实现的,管我们什么事?我们会用就可以了。

面向对象的底层其实还是面向过程,把面向过程抽象成类,然后封装,方便我们我们使用的就是面向对象了。

就不叭叭那么多了,直接上案例(烟花效果)

思路:

【1】创建对象
1】烟花 function Fire
2】烟火 function Spark
【2】描述对象
1】烟花
静态属性
生成的烟花天添加的元素(body)
烟花的位置(x,y)
烟火数量
烟火的爆炸的半径
动态方法
初始化 init
烟花向上移动 fireMove
爆炸成烟火 boom
2】烟火
静态属性
烟火的颜色
烟火的位置 top left
动太方法
初始化 init
烟火的移动 sparkMove
移动结束之后 移出元素(把烟火和烟花都移出)remove
【3】操作对象
点击页面中的某个位置是生成 烟花(烟花对象),烟花爆炸之后生成烟火(调用烟火对象)

具体如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
     
     
            margin: 0;
            padding: 0;
        }
        
        html,
        body {
     
     
            overflow: hidden;
            height: 100%;
        }
        
        body,
        div,
        p {
     
     
            margin: 0;
            padding: 0;
        }
        
        body {
     
     
            background: #000;
            font: 12px/1.5 arial;
            color: #7A7A7A;
        }
        
        a {
     
     
            text-decoration: none;
            outline: none;
        }
        
        #tips,
        #copyright {
     
     
            position: absolute;
            width: 100%;
            height: 50px;
            text-align: center;
            background: #171717;
            border: 2px solid #484848;
        }
        
        #tips {
     
     
            top: 0;
            border-width: 0 0 2px;
        }
        
        #tips a {
     
     
            font: 14px/30px arial;
            color: #FFF;
            background: #F06;
            display: inline-block;
            margin: 10px 5px 0;
            padding: 0 15px;
            border-radius: 15px;
        }
        
        #tips a.active {
     
     
            background: #FE0000;
        }
        
        .fire {
     
     
            width: 3px;
            height: 30px;
            background: white;
            position: absolute;
            top: 100%;
        }
        
        .spark {
     
     
            position: absolute;
            width: 10px;
            height: 10px;
            border-radius: 50%;
            left: 0;
            top: 0;
        }
    </style>
</head>

<body>
    <div id="tips">
        <a href="javascript:;" id="auto">自动播放</a>
    </div>

    <script src="utils.js"></script>
    <!--     
【1】创建对象
    1】烟花 function Fire
    2】烟火 function Spark
【2】描述对象
    1】烟花
        静态属性
            生成的烟花天添加的元素(body)
            烟花的位置(x,y)
            烟火数量
            烟火的爆炸的半径
        动态方法
            初始化 init
            烟花向上移动 fireMove
            爆炸成烟火 boom
    2】烟火
        静态属性
            烟火的颜色
            烟火的位置 top left
        动太方法
            初始化 init
            烟火的移动 sparkMove
            移动结束之后 移出元素(把烟火和烟花都移出)remove
【3】操作对象
    点击页面中的某个位置是生成 烟花(烟花对象),烟花爆炸之后生成烟火(调用烟火对象) -->
    <script>
        let ele = document.body;
        let auto = $('#auto')

        let flag = true; //给一个标识,点击的时候表示自动放烟花还是停止
        let timer;
        auto.onclick = function(e) {
     
     
            e.cancelBubble = true;
            // 如果flag = true,那么就表示点击自动放烟花
            if (flag) {
     
     
                // 在自动放烟花的过程中,flag = false
                flag = false;
                timer = setInterval(() => {
     
     
                    new Fire(ele);
                }, 1000)

            } else {
     
     
                // flag = false时候,正在放烟花,点击的时候停止放烟花
                flag = true;
                clearInterval(timer)
            }
        }

        // 点击任意位置时产生烟花
        document.onclick = function(e) {
     
     
            // console.log(1)
            // 获取鼠标点击的位置
            let x = e.clientX; // 鼠标的水平位置
            let y = e.clientY; // 鼠标的垂直位置
            new Fire(ele, x, y)
        }

        // 创建烟花对象
        function Fire(ele, left, top) {
     
     
            this.ele = ele;
            this.left = left || getRandom(100, innerWidth - 100);
            this.top = top || getRandom(100, innerHeight - 100);
            this.r = getRandom(60, 100);
            this.num = getRandom(20, 40)

            // 初始化函数
            this.init()
        }

        // 描述对象
        Fire.prototype = {
     
     
            // 初始化
            init() {
     
     
                // 创建一个标签节点 
                this.div = document.createElement('div');
                // 添加class名
                this.div.classList.add('fire');
                this.div.style.left = this.left + 'px';
                this.ele.appendChild(this.div);

                // 调用烟花移动
                this.fireMove()
            },
            // 烟花移动 (调用封装好的运动函数move())
            fireMove() {
     
     
                // console.log(this.div)
                move(this.div, {
     
     
                    top: this.top,
                    height: 2, // 烟花的高度
                    // opacity: 0.1  // 为什么给了透明后烟花不会爆炸?
                }, () => {
     
      // 这里要使用箭头函数,如果使用普通函数的话this指向的是widow
                    this.boom();
                    // 当烟火爆炸的时候 烟花编程透明色
                    move(this.div, {
     
     
                        opacity: 0
                    })
                })
            },
            // 烟花爆炸
            boom() {
     
     
                // console.log('爆炸')
                // 当烟花到指定的位置后爆炸
                let deg = 360 / this.num; // 每一份得到的角度
                let degree = 0;
                for (let i = 1; i <= this.num; i++) {
     
     
                    degree += deg; // 每循环一次,角度都会跟着变化
                    let radian = (Math.PI * degree) / 180; // 求弧度

                    // 所产生烟火的位置
                    let left = parseInt(Math.cos(radian) * this.r);
                    let top = parseInt(Math.sin(radian) * this.r);

                    // 构造一个烟火对象 Spark()
                    new Spark(this.div, left, top)
                }
            }
        }

        // 对象的属性修改
        Object.defineProperty(Fire.prototype, 'constructor', {
     
     
            value: Fire
        })

        // 创建烟火对象
        function Spark(ele, left, top) {
     
     
            this.ele = ele;
            this.color = getRandomColor();
            this.left = left || getRandom(100, innerWidth - 100);
            this.top = top || getRandom(100, innerHeight - 100);
            // 调用初始化函数
            this.init();
        }

        Spark.prototype = {
     
     
            init() {
     
     
                this.span = document.createElement('span');
                this.span.classList.add('spark');
                this.span.style.background = this.color;
                this.ele.appendChild(this.span);

                // console.log(this.span)
                // 调用sparkMove
                this.sparkMove()
            },
            sparkMove() {
     
     
                move(this.span, {
     
     
                    left: this.left,
                    top: this.top
                }, () => {
     
     
                    // 移除烟花
                    this.removeEle();
                })
            },
            // 爆炸后移除烟花及烟火
            removeEle() {
     
     
                this.ele.remove();
            }
        }
        Object.defineProperty(Spark.prototype, 'constructor', {
     
     
            value: Spark
        })
    </script>
</body>

</html>

调用了untils.js文件


// 获取样式的方法
// 有两个参数
// 参数1:元素
// 参数2:csss属性
function getStyle(ele, attr) {
    
    
    return style = window.getComputedStyle ? window.getComputedStyle(ele)[attr] : ele.currentStyle[attr]
}


// 封装一个事件监听的函数(兼容)
// 参数:事件源,事件类型,回调函数
function addEvent(ele, type, callback) {
    
    
    if (ele.addEventListener) {
    
    
        ele.addEventListener(type, callback);
    } else {
    
    
        ele.attachEvent('on' + type, callback)
    }
}

// 动画函数
function move(ele, obj, callback) {
    
    
    let speed;
    let index = 0; //记录定时器的个数
    // 循环对象创建定时器
    for (let attr in obj) {
    
    
        // 透明度的变化的时候 0-1
        // console.log(attr);
        index++;
        // 清除上一次的定时器
        clearInterval(ele[attr])
            // 属性:attr
            // 属性值:obj[key]
            // box['width'] 给box这个dom元素添加一个 width属性(dom属性)
            // dom 对象,以地址形式存储的,当上一次更改dom对象中的值,那么这次获取这个对象的时候是能拿到被更改之后的dom对象
        ele[attr] = setInterval(() => {
    
    
            // 把透明度的取值 改边为0-100的取值
            // 0-1=====》0-100
            let style;
            if (attr == 'opacity') {
    
    
                style = getStyle(ele, attr) * 100;
            } else {
    
    
                style = parseInt(getStyle(ele, attr));
            }

            speed = (obj[attr] - style) / 5;
            speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
            style += speed;


            if (attr === 'opacity') {
    
    
                ele.style[attr] = style / 100;
            } else {
    
    
                ele.style[attr] = style + 'px';
            }

            if (style == obj[attr]) {
    
    
                clearInterval(ele[attr]);
                // 有多少个属性参数动画就会执行多少次
                // 执行一次怎么?
                // 没清除一次定时器,那么定时器的个数 -1
                index--;
                // 当定时器的个数 为0 的时候,说明所有动画执行完毕
                if (index === 0) {
    
    
                    callback && callback();
                }
            }
        }, 50)
    }
}

function $(selector) {
    
    
    return document.querySelector(selector);
}

猜你喜欢

转载自blog.csdn.net/weixin_43901780/article/details/108108757