JS 面向对象 实现烟花特效

基本效果如图:
在这里插入图片描述
这里的烟花特效 是配合鼠标点击去实现的 (你要是想绑定别的事件也可)

  1. 创建一个烟花,从底部升起运动到目标位置
  2. 到达目标位置之后,删除它的同时 炸出一堆烟花

HTML布局+CSS样式
    <div class="container"></div>
    <style>
        .container{
            width: 80%;
            height: 300px;
            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>

JavaScript代码
// OOA
    // 1.创建一个烟花元素
    // 2.元素运动 运动结束之后删除
    // 3.烟花爆炸 循环多个烟花  爆炸之后也要删除
    // 4.随机位置
    // 5.烟花的随机颜色
// OOD
    // function Firework(x,y){
    //     this.init(x,y);
    // }
    
    // Firework.prototype = {
    //     constructor : Firework,
    //     // 初始化
    //     init : function(x,y){//xy是目标位置
    //         // 创建元素
    //         // 元素运动  把目标点当做参数x、y
    //         // 调用函数

    //     },
    //     // 1.创建元素
    //     createFireWorkEle : function(){

    //     },
    //     // 2.元素运动
    //     fireWorkUp : function(ele){
    //         // 两部分运动 left直接到达、top运动达到
    //     },
    //     // 3.烟花爆炸
    //     fireWorkBlast : function(){
    //         // 3.1创建非常多的元素
    //     },
    //     // 4.随机位置
    //     randomBoundary : function(){

    //     },
    //     // 5.随机颜色
    //     randomColor : function(ele){

    //     }
    // }
    <script>
    // OOP
        function Firework(x,y , selector){
            // 选择父级元素
            this.main = document.querySelector(selector);
            
            this.init(x,y);
        }
        
        Firework.prototype = {
            constructor : Firework,
            // 初始化
            init : function(x,y){
                //x、y是点击事件创建的烟花的位置
                this.x = x;
                this.y = y;

                // 创建元素
                this.ele = this.createFireWorkEle();
                // 爆炸烟花的随机位置 最大值
                this.left_max = this.main.offsetWidth - this.ele.offsetWidth;
                this.top_max = this.main.offsetHeight - this.ele.offsetHeight;

                // 元素添加背景色
                this.randomColor(this.ele);
                // 烟花主体升起
                this.fireWorkUp(this.ele );
                // 烟花爆炸
                this.fireWorkBlast(this.ele);
            },
            // 1.创建元素
            createFireWorkEle : function(){
                // 往containe里面放进一个烟花fire
                var ele = document.createElement("div");
                ele.className = "fire";
                // 在页面显示 
                this.main.appendChild(ele);
                return ele;
            },
            // 2.元素运动
            fireWorkUp : function(ele){
                // 两部分的运动 left直接到达、top运动达到
                ele.style.left = this.x + "px";
                animate(ele, {top : this.y} , function(){
                    // 烟花运动结束后 要删除它
                    // console.log(this);//这时候指向windoe,用bind修改指向
                    ele.remove();
                    // 然后调用烟花爆炸
                    this.fireWorkBlast();
                }.bind(this));
            },
            // 3.烟花爆炸
            fireWorkBlast : function(){
                // 3.1创建非常多的元素
                for(var i = 0 ; i < 20 ; i ++){
                    var ele = this.createFireWorkEle();
                    this.randomColor(ele);
                    // 3.1初始样式设置
                    ele.style.left = this.x + "px";
                    ele.style.top = this.y + "px";
                    // 和点击之后创建的烟花 区分开
                    ele.style.borderRadius = "50%";
                    // 3.3让元素有运动目标
                    animate(ele , this.randomBoundary(ele) , function(callback_ele){
                        // 爆炸之后删除所有元素
                        // 用bind 给每个匿名函数都绑定一个ele。否则只会删除最后一个ele
                        callback_ele.remove();
                    }.bind(this , ele));
                }
            },
            // 4.随机位置
            randomBoundary : function(){
                // min 是0 
                // max中offset性能消耗大,所以放在init()里,只获取一次即可
                return{
                    left : parseInt(Math.random()*(this.left_max + 1)),
                    top : parseInt(Math.random()*(this.top_max + 1))
                }
            },
            // 5.随机颜色
            randomColor : function(ele){
                // 随机颜色方法很多
                var r = parseInt(256 * Math.random());
                var g = parseInt(256 * Math.random());
                var b = parseInt(256 * Math.random());
                var random_color = "rgb("+r + "," + g + "," + b +")";
                return ele.style.backgroundColor = random_color;
                
            }
        }

        document.querySelector(".container").addEventListener("click",function(evt){
            var e = evt || event;
            new Firework(e.offsetX , e.offsetY , ".container");
        })
    </script>


script 引入的 "animate.js" 运动封装
//               元素,属性,回调函数(动画执行结束,调用这个函数)
function animate( ele , attr_options , callback ){
    // 获取当前属性
    for(var attr in attr_options){
        // 同时判断是否是opacity属性
        attr_options[attr] = {
            // 目标点(传入的数据)
            target : attr === "opacity" ? 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 item = attr_options[attr];
            // console.log(item , attr);//target和iNow , "属性名"
            var target = item.target;
            var iNow   = item.iNow;
            // 计算速度
            var speed = (target - iNow) / 10;
            // 速度取整
            speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
            // 运动的终止条件  
            // (目标 - 当前位置) 的绝对值 <= 速度 , 此时判定已经到达
            if( Math.abs( target - iNow) <= Math.abs(speed) ){
                // 送他到底目标点
                ele.style[attr] = attr === "opacity" ? target / 100 :  target + "px";
                // if里的终止条件不严谨:
                // 因为目标的不一致会让运动次数执行不同,有可能会提前关闭定时器
                // 解决办法:完成一条运动后 删除对象里的数据
                delete attr_options[attr];
            
                for(var num in attr_options){
                    // 如果attr_options里面有属性,不终止定时器
                    return false;
                }
                // 如果对象里面没有属性了,就可以关闭定时器
                clearInterval(ele.timer);
                // 可能会不传callback
                typeof callback === "function" ? callback() : "";
            }else{
                // 元素继续运动
                // 如果直接设置iNow 每次循环iNow都会被重置,iNow是一个临时变量
                // 所以不能去操作iNow,要去操作iNow的数据源
                attr_options[attr].iNow += speed;
                ele.style[attr] = attr === "opacity" ? attr_options[attr].iNow / 100 : attr_options[attr].iNow + "px";
            }
        }
    } , 30)
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值