原生JS实现定时器多段动画

2020-11-26 15:00:14 浏览数 (1)

分享一个用原生JS实现的定时器多段动画,效果如下:

代码实现如下,详情请看代码注释:

代码语言:javascript复制
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>原生JS实现定时器多段动画</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        #btn1 {
            position: relative;
            left: 50%;
            top: 300px;
            transform: translate(-50%, -50%);
        }

        #box {
            width: 100px;
            height: 100px;
            background-color: red;
            position: absolute;
            left: 50%;
            top: 50%;
            margin-left: -50px;
            margin-top: -50px;
        }
    </style>
</head>

<body>
    <button id="btn1">运动</button>
    <div id="box"></div>
    <script>
        var btn1 = document.getElementById("btn1");
        var box = document.getElementById("box");
        var timer = null;
        btn1.onclick = function () {

            // 我们想要通过多次调用animate,实现多段运动
            // 但是只会执行后一个,原因是后面的调用将前面的调用定时器清除
            // 我们需要的是当第一次运动完成后,再去执行第二个运动

            // 代码修改后
            animate(box, {
                width: 200,
                height: 170,
                left: 130,
                top: 240,
                opacity: 0.5,
                zIndex: 3
            }, function () {
                animate(box, {
                    width: 300,
                    height: 270,
                    left: 230,
                    top: 140,
                    opacity: 0.7,
                    zIndex: 1
                });
            });
        };
        animate(box, {
            width: 100,
            height: 200
        }, function () { });


        // 可以让多个样式同时进行运动的animate
        function animate(tag, obj, fn) {
            // 停止加速
            clearInterval(tag.timer);
            tag.timer = setInterval(function () {
                // 假设本次可以进行清除
                var flag = true;
                for (var k in obj) {
                    // 针对opacity和zIndex进行单独处理
                    if (k == "opacity") {
                        var target = obj[k] * 100;
                        var leader = getStyle(tag, k) * 100 || 0;
                        var step = (target - leader) / 10;
                        // 设置取整,保证元素可以进行运动
                        step = step > 0 ? Math.ceil(step) : Math.floor(step);
                        leader = leader   step;
                        // 缩小对应的倍数,并且去除单位
                        tag.style[k] = leader / 100;
                    } else if (k == "zIndex") {
                        // zIndex不需要运动,只要进行修改设置即可
                        tag.style.zIndex = obj[k];
                    } else {
                        // k - 属性名 - attr - 要修改的样式名
                        // obj[k] - 属性值 - target - 要修改的样式的目标值
                        var target = obj[k];
                        var leader = parseInt(getStyle(tag, k)) || 0;
                        var step = (target - leader) / 10;
                        // 设置取整,保证元素可以进行运动
                        step = step > 0 ? Math.ceil(step) : Math.floor(step);
                        leader = leader   step;
                        tag.style[k] = leader   "px";
                    }
                    // 如果有某一个样式没有运动到指定位置,阻止清除
                    if (leader != target) {
                        flag = false;
                    }
                };
                if (flag) {
                    clearInterval(tag.timer);
                    fn && fn();
                }
            }, 20);
        };
        // 由于获取标签任意样式的值
        function getStyle(tag, attr) {
            if (tag.currentStyle) {
                return tag.currentStyle[attr];
            } else {
                return getComputedStyle(tag, null)[attr];
            }
        }
    </script>
</body>

</html>

0 人点赞