js表白-心形烟花

心形烟花

 

<!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>
        .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: 6px;
            height:6px;
            position: absolute;
            animation: fireBug 3s infinite;
            bottom: 0;
        }
        @keyframes fireBug{
                  0% {opacity:1;}
                  50% {opacity:0.2;}
                  100% {opacity:1;}
            }
    </style>

</head>
<body>
    <div class="container">

    </div>
    <script src="./animate-opacity.js"></script>
</body>
<script>

    class FireWork{
        constructor(options){
            //单例模式 如果 FireWork上已经有选择好的元素了,那么我们就不需要重复进行选择了
            if(FireWork.main && FireWork.main.selector === options.main){
                //已经经历过元素选择了,所以直接赋值
                this.main = FireWork.main.ele;
            }else{
                //还没有进行元素选择;
                //将需要获取的DOM放入对象中 , 进行判断的也放入对象中
                FireWork.main = {
                    ele : document.querySelector(options.main),
                    selector : options.main
                }
                this.main = FireWork.main.ele;
            }
            //获取烟花爆炸的方式,并放入原型中
            this.blast_type = options.blast_type;
           //将传入的需要创建的子元素tagName放入原型中
            this.ele_tagName = options.children;
            //将获取传入的鼠标点击位置
            this.x = options.x;
            this.y = options.y;
            //调用初始化方法
            this.init()
        }
        init(){
            //创建DIV
            this.ele = this.createFireWork()
            //设置边界
            this.left_max = this.main.offsetWidth - this.ele.offsetWidth;
            this.top_max   = this.main.offsetHeight - this.ele.offsetHeight;
            //调用烟花上升的方法
            this.fireWorkUp(this.ele)
        }
        //创建DIV
        createFireWork(){
            var ele = document.createElement(this.ele_tagName)
            ele.className = "fire"
            //调用方法设置随机颜色
            this.randomColor(ele);
            return  this.main.appendChild(ele)
        }
        //设置烟花上升
         fireWorkUp(ele){
             //设置烟花上升的横坐标
           ele.style.left = this.x + "px";  
           //调用封装好的运动JS , 设置元素想上运动   
            animate(ele , {top : this.y} , function(){
                //烟花到达指定地点之后消失
                ele.remove();
                //调用烟花的爆炸效果
                this.fireWorkBlast()
            }.bind(this))
        }
        //烟花爆炸效果
        fireWorkBlast(){
           //设置烟花爆炸之后散发的光点个数 
            for(var i = 0; i < 100; i++){
                //创建对应的DIV
                var ele = this.createFireWork()
                //设置随机颜色
                this.randomColor(ele);
                //设置随机位置
                ele.style.left = this.x + "px";
                ele.style.top = this.y + "px";
                ele.style.borderRadius = "50%";
               //判断爆炸之后的形状
                switch(this.blast_type){
                    //爆炸之后成圆形
                    case "circle":
                        //设置散发之后成一个圆形
                        animate(ele ,this.circleBlast( i , 20),function(ele){
                            //运动完成之后消失
                            ele.remove()
                        }.bind(this , ele));
                        break;
                    //爆炸之后成心形
                    case "heart":
                        //设置散发之后成一个爱心
                        animate(ele , this.heartBlast(i),function(ele){
                            ele.remove()
                        }.bind(this , ele))
                        break
                    //爆炸之后随机运动
                    default :
                        animate(ele , this.randomPosition(),function(ele){
                            ele.remove()
                        }.bind(this , ele))
                        break
                }
            }
        }
        //设置随机颜色
        randomColor(ele){
            return ele.style.backgroundColor = "#" + parseInt(parseInt("ffffff" , 16) * Math.random()).toString(16).padStart(6,0);
        }
        //散发随机位置
        randomPosition(){
            return {
                left : parseInt(Math.random() * (this.left_max + 1)),
                top : parseInt(Math.random() * (this.top_max + 1))
            }
        }
        //散发形成一个圆形
        circleBlast(index , all){
            var r  = 100;
            var reg = (360 / all) * index;
            var deg = Math.PI / 180 * reg;
            return {
                left : parseInt(r * Math.cos( deg )) + this.x,
                top  : parseInt(r * Math.sin( deg )) + this.y
            }
        }
        //散发成一个爱心
        heartBlast(i){
            var r  = 60;
            var m = i;
            var n = -r * (((Math.sin(i) * Math.sqrt(Math.abs(Math.cos(i)))) / (Math.sin(i) + 1.4)) - 2 * Math.sin(i) + 2);
            return {
                left : n * Math.cos(m) + this.x,
                top  : n * Math.sin(m) + this.y
            }
        }

    }

    var ele_con = document.querySelector(".container")
    ele_con.addEventListener("click" , function(evt ){
            var e = evt || event;
            new FireWork({
            main : ".container",
            children : "div",
            x : e.offsetX , 
            y : e.offsetY,
            blast_type : "heart" //设置烟花爆炸之后的形状
        });
    })
</script>
</html>

引入的的js文件

function animate( ele , attr_options , callback ){
    for(var attr in attr_options){
        // console.log(attr_options , attr_options[attr])
        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])
        }
        // console.log(attr_options , attr_options.width)
    }
    // 关闭开启定时器;
    clearInterval( ele.timer );
    ele.timer = setInterval( function(){
        // 1. 获取速度; width :  height : 
        for(var attr in attr_options){
            // attr : width | height;
            var item = attr_options[attr];
            // console.log(item , attr);
            var target = item.target;
            var iNow   = item.iNow;
            // 运动所必须的值我们都有了;
            // 计算速度;
            var speed = (target - iNow) / 20;
            // 速度取整;
            speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);

            // 终止条件 : 
            if( Math.abs( target - iNow) <= Math.abs(speed) ){
                // 终止定时器 ; 
                // 送他一把;
                // clearInterval( ele.timer );
                // ele.style[attr] = target + "px";
                // 终止条件不可靠,因为目标的不一致会让运动次数执行不同,有可能提前关闭定时器;
                ele.style[attr] = attr === "opacity" ? target / 100 :  target + "px";
                // 一条运动完成删除对象里面的数据;
                delete attr_options[attr];

                // 如果对象里面没有属性了,那么我们关闭定时器就可以了;
                for(var num in attr_options){
                    // 如果attr_options里面有属性,那么此时我就不应该终止定时器;
                    return false;
                }
                clearInterval(ele.timer);
                typeof callback === "function" ? callback() : "";
            }else{
                // 元素运动;
                // 因为 iNow 是一个临时变量,所以不能再去操作iNow , 要去操作iNow 的数据源;
                // 多花点经历理解这段代码;
                attr_options[attr].iNow += speed;
                ele.style[attr] = attr === "opacity" ? attr_options[attr].iNow / 100 : attr_options[attr].iNow + "px";
            }
        }
    } , 30)
}

 

posted @ 2020-03-22 23:57  逝水流年0  阅读(2350)  评论(0编辑  收藏  举报