05-JS特效-缓动动画

动画的种类

动画原理 = 盒子位置 + 步长。

1.闪动。 (瞬间到达)
2.匀速。 (每次走一样距离)
3.缓动。 (开始特快越走越慢,步长越来越小.类似刹车,电梯停止,压缩弹簧…)

缓动动画原理

缓动动画原理: 盒子位置 + 步长(步长越来越小)

盒子位置 = 盒子本身位置+(目标位置-盒子本身位置)/ 10;

公式: leader = leader + (target - leader) / 10;

缓动动画用到的三个Math方法

Math.ceil(); 向上取整
Math.floor(); 向下取整
Math.round(); 四舍五入取整

0.缓动动画封装

    <style>
       div {
            width: 100px;
            height: 100px;
            background-color: pink;
            position: absolute;
        }
    </style>
    <body>
    <button>走到200</button>
    <button>走到400</button>
    <div></div>
    <script>

    //获取元素
    var div = document.getElementsByTagName("div")[0];
    var btnArr = document.getElementsByTagName("button");

    //绑定事件
    btnArr[0].onclick = function () {
        //封装一个方法,调用这个函数。带两个参数。一个是盒子,一个是目标。
        animate(div,20);
    }
    btnArr[1].onclick = function () {
        animate(div,400);
    }

    //缓动动画封装

    function animate(ele,target){
        clearInterval(ele.timer);
        ele.timer = setInterval(function () {
            var leader = ele.offsetLeft;
            var step = (target-leader)/10;
            //二次处理步长:大于0向上取整,小于0向下取整
            step = step>0 ?Math.ceil(step) :Math.floor(step);
            ele.style.left = leader +step +"px";
            if(Math.abs(target-leader)<Math.abs(step)){
                ele.style.left = target +"px";
                clearInterval(ele.timer);
            }
        },30);
    }

    </script>
    /body>

1. 缓动框架封装(单个属性)

     <style>
        div {
            width: 100px;
            height: 100px;
            background-color: pink;
            position: absolute;
        }
    </style>
    </head>
    <body>
    <button>动起来...</button>
    <div></div>

    <script>

        var btn = document.getElementsByTagName("button")[0];
        var box = document.getElementsByTagName("div")[0];

        btn.onclick = function () {
            animate(box,"top",400);
            //animate(box,"width",400);
            //animate(box,"height",400);
        }

        //缓动动画:(设置单个属性的值需要多出一个参数。属性)
        function animate(ele,attr,target){
            clearInterval(ele.timer);
            ele.timer = setInterval(function () {
                //获取盒子自身的位置不能再用检测的方法了:offsetLeft;
                    //改用自己封装的获取样式的方法;既能获取内嵌式和行内式又可以获取外链式
                var leader = parseInt(getStyle(ele,attr)) || 0;//带有单位,需要去掉px
                //获取步长
                var step = (target-leader)/10;
                step = step>0?Math.ceil(step):Math.floor(step);
                //赋值的时候要用传过来的属性
                ele.style[attr] = leader + step +"px";
                console.log(1);
                if(Math.abs(target-leader)<=Math.abs(step)){
                    ele.style[attr] = target+"px";
                    clearInterval(ele.timer);
                }
            },30);
        }


        //封装一个兼容写法:
        function getStyle(ele,attr){
            //如果浏览器支持该方法,那么返回值是一个函数体;如果不支持是undefined;
            if(window.getComputedStyle){
                return window.getComputedStyle(ele,null)[attr];
            }else{
                return ele.currentStyle[attr];
            }
        }

    </script>
    /body>

2. 缓动框架封装(多个属性)利用json实现

        <style>
        div {
            width: 100px;
            height: 100px;
            background-color: pink;
            position: absolute;
            /*margin-left: 100px;*/
        }
        </style>
        </head>
        <body>
        <button>动起来...</button>
        <div></div>


        <script>

        var btn = document.getElementsByTagName("button")[0];
        var box = document.getElementsByTagName("div")[0];


        btn.onclick = function () {
        //缓动动画
        var obj1 = {"left": 800, "top": 200, "width": 200, "height": 200};
        animate(box, obj1);

    }
    function animate(ele, json) {
        clearInterval(ele.timer);
        ele.timer = setInterval(function () {
            //多个属性操作:很简单。
            //1.利用for...in循环。
            //2.把程序中的attr换成for...in中的k。
            //3.把程序中的target换成for...in中的json[k]。
            for (var k in json) {
                var leader = parseInt(getStyle(ele, k)) || 0;//带有单位,需要去掉px
                //获取步长
                var step = (json[k] - leader) / 10;
                step = step > 0 ? Math.ceil(step) : Math.floor(step);
                //赋值的时候要用传过来的属性
                ele.style[k] = leader + step + "px";
                console.log(1);
                //定时器最难清除,一会儿再做。。。。

            }

        }, 30);
    }


    //封装一个兼容写法:
    function getStyle(ele, attr) {
        //如果浏览器支持该方法,那么返回值是一个函数体;如果不支持是undefined;
        if (window.getComputedStyle) {
            return window.getComputedStyle(ele, null)[attr];
        } else {
            return ele.currentStyle[attr];
        }
    }

    </script>
    </body>

3. 缓动框架封装(清除定时器)

    <style>
        div {
            width: 100px;
            height: 100px;
            background-color: pink;
            position: absolute;
        }
    </style>
    </head>
    <body>
    <button>动起来</button>
    <div></div>
    <script>

        var btn = document.getElementsByTagName("button")[0];
        var box = document.getElementsByTagName("div")[0];

        btn.onclick = function () {
            var obj1 = {"left":800,"top": 200,"width":200,"height":200};
            animate(box,obj1);

        }

        function animate(ele,json){
            clearInterval(ele.timer);
            ele.timer = setInterval(function () {
                //定义一个开闭原则
                var bool = true;

                for(var k in json){
                    var leader = parseInt(getStyle(ele,k)) || 0;//带有单位,需要去掉px
                    //获取步长
                    var step = (json[k]-leader)/10;
                    step = step>0?Math.ceil(step):Math.floor(step);
                    //赋值的时候要用传过来的属性
                    leader = leader + step;
                    ele.style[k] = leader +"px";
                    console.log(1);
                    //定时器最难清除,必须保证所有属性都到达指定位置,才能清除定时器
                    //再次启用开闭原则:有一个没有到达目标位置,也不能清除定时器
                    //if(Math.abs(json[k]-leader)>Math.abs(step)){
                    //没到达指定位置,就是当前位置和目标位置不相等
                    if(json[k]!=leader){
                        //不能清除定时器
                        bool = false;
                    }
                }
                //看看这个bool类型值是否被修改,如果是默认true代表所有元素都到达指定位置,就可以清除定时器了。
                if(bool){
                    clearInterval(ele.timer);
                }
            },30);
        }


        //封装一个兼容写法:
        function getStyle(ele,attr){
            //如果浏览器支持该方法,那么返回值是一个函数体;如果不支持是undefined;
            if(window.getComputedStyle){
                return window.getComputedStyle(ele,null)[attr];
            }else{
                return ele.currentStyle[attr];
            }
        }

    </script>
    </body>

4. 缓动框架封装(回调函数)

    <style>
        div {
            width: 100px;
            height: 100px;
            background-color: pink;
            position: absolute;
            /*margin-left: 100px;*/
        }
    </style>
    </head>
    <body>
    <button>动起来...</button>
    <div></div>


    <script>

        var btn = document.getElementsByTagName("button")[0];
        var box = document.getElementsByTagName("div")[0];


        btn.onclick = function () {
            //缓动动画
            var obj1 = {"left":400};
            var obj2 = {"top":400};
            //回调函数
            animate(box,obj1, function () {
                animate(box,obj2);
            });
            //走完第一个在走第二个:1.第一个定时器被清除的时候就可以走第二个函数来了。


        }

        //加一个fn,带表一个函数,当前一个定时器被清除的时候,在执行这个函数
        function animate(ele,json,fn){
            clearInterval(ele.timer);
            ele.timer = setInterval(function () {
                //定义一个开闭原则
                var bool = true;

                for(var k in json){
                    var leader = parseInt(getStyle(ele,k)) || 0;//带有单位,需要去掉px
                    //获取步长
                    var step = (json[k]-leader)/10;
                    step = step>0?Math.ceil(step):Math.floor(step);
                    //赋值的时候要用传过来的属性
                    leader = leader + step;
                    ele.style[k] = leader +"px";
                    console.log(1);
                    //定时器最难清除,必须保证所有属性都到达指定位置,才能清除定时器
                    //再次启用开闭原则:有一个没有到达目标位置,也不能清除定时器
                    //没到达指定位置,就是当前位置和目标位置不相等
                    if(json[k]!=leader){
                        //不能清除定时器
                        bool = false;
                    }
                }
                //看看这个bool类型值是否被修改,如果是默认true代表所有元素都到达指定位置,就可以清除定时器了。
                if(bool){
                    clearInterval(ele.timer);
                    //定时器被清除了,我可以执行fn这个函数了。
                        //判断:如果传递了函数就执行,如果没有传递,不管他
                    if(fn){//如果fn存在将代表函数体,如果不存在代表undefined
                        fn();
                    }
                }
            },30);
        }



        //封装一个兼容写法:
        function getStyle(ele,attr){
            //如果浏览器支持该方法,那么返回值是一个函数体;如果不支持是undefined;
            if(window.getComputedStyle){
                return window.getComputedStyle(ele,null)[attr];
            }else{
                return ele.currentStyle[attr];
            }
        }

    </script>
    </body>

5. 缓动框架封装(特殊属性处理透明度和层级)

    <style>
        *{
            padding: 0;
            margin: 0;
        }
        div {
            width: 100px;
            height: 100px;
            background-color: pink;
            position: absolute;
        }
    </style>
    </head>
    <body>
    <button>动起来</button>
    <div></div>
    <script>

        var btn = document.getElementsByTagName("button")[0];
        var box = document.getElementsByTagName("div")[0];

        btn.onclick = function () {
            //缓动动画
//            var obj1 = {"left":400};
            var obj1 = {"opacity": 0.4};
//            var obj1 = {"z-index": 2};
//            var obj1 = {"background-color": "pink"};
            //回调函数
            //特殊属性特殊处理
            animate(box,obj1);
        }

        function animate(ele,json,fn){
            clearInterval(ele.timer);
            ele.timer = setInterval(function () {
                //定义一个开闭原则
                var bool = true;
                for(var k in json){
                    //需求:特殊属性特殊处理。if判断如果是什么属性怎么处理,如果是另外一个属性,怎么处理....
                    //如果是层级,我们这么处理(k的值为z-index)
                    if("z-index" === k){
                        //层级不是缓慢移动到最高的,而是一次性提到最好。(需求决定)
                        //事件触发瞬间,层级立刻提高到最高,不能慢慢移动到最高。
                        ele.style.zIndex = json[k];
                    //如果是透明度我们这么处理
                    }else if("opacity" === k){
                        //问题1:透明度的值是小数,所以应该*100之后计算。(兼容IE678方便计算)
                        //问题2:透明度的兼容性不好。如果想要兼容IE678,要使用filter。(*100)

                        // 先获取透明度,然后*100在取整(小数精度丢失问题)。
                        // 如果没有给opacity属性,那么默认1,*100之后值为100;
                        var leader = parseInt(getStyle(ele,k)*100) || 100;
                        var step = (parseInt(json[k]*100)-leader)/10;
                        step = step>0?Math.ceil(step):Math.floor(step);
                        leader = leader + step;
                        //直接为opacity赋值,不需要加单位px;
                            //opacity要的是0-1之间的小数,所以除以100;
                        ele.style.opacity = leader/100;
                        //兼容ie678,不需要除以100,因为filter的值为100进制。
                        ele.style.filter = "alpha(opacity="+leader+")";
                        console.log(1);
                        if(parseInt(json[k]*100)!=leader){
                            //不能清除定时器
                            bool = false;
                        }
                    //普通属性普通处理
                    }else{
                        var leader = parseInt(getStyle(ele,k)) || 0;//带有单位,需要去掉px
                        var step = (json[k]-leader)/10;
                        step = step>0?Math.ceil(step):Math.floor(step);
                        leader = leader + step;
                        ele.style[k] = leader +"px";
                        console.log(1);
                        //if(Math.abs(json[k]-leader)<=Math.abs(step)){:对小数也可以赋值
                        if(json[k]!=leader){
                            //不能清除定时器
                            bool = false;
                        }
                    }
                }
                if(bool){
                    clearInterval(ele.timer);
                    if(fn){
                        fn();
                    }
                }
            },30);
        }

        //封装一个兼容写法:
        function getStyle(ele,attr){
            //如果浏览器支持该方法,那么返回值是一个函数体;如果不支持是undefined;
            if(window.getComputedStyle){
                return window.getComputedStyle(ele,null)[attr];
            }else{
                return ele.currentStyle[attr];
            }
        }

    </script>
    </body>

案例

1.筋斗云
2.仿360开机页面
3.手风琴
4.旋转木马轮播图

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值