原生js实现简单动画效果

使用原生js实现简单动画效果

实现动画效果可以用jQuery提供的animate方法,或一些插件来实现,但是随着前端组件化开发的流行,
jQuery大量的DOM操作已经显得十分多余,正在逐渐从前端技术栈中被淘汰,下面我们使用原生js实现简单的匀速动画效果和缓动效果

匀速动画实现水平移动
css样式

<style>
        #box {
            width: 100px;
            height: 100px;
            background-color: pink;
            position: absolute;
            top: 100px;
            left: 0px;
        }

        .line400 {
            width: 1px;
            height: 100px;
            background-color: red;
            position: absolute;
            left: 400px;
            top: 100px;
        }

        .line800 {
            width: 1px;
            height: 100px;
            background-color: red;
            position: absolute;
            left: 800px;
            top: 100px;
        }
    </style>

html结构和js代码

<body>
    <div id="box"></div>
    <div class="line400"></div>
    <div class="line800"></div>

    <input type="button" value="右移400" id="r1">
    <input type="button" value="右移800" id="r2">

    <script>
        var box = document.getElementById("box");
        var box2 = document.getElementById("box2");
        var btnR1 = document.getElementById("r1");
        var btnR2 = document.getElementById("r2");

        btnR1.onclick = function () {
            Animation(box, 400);
        };

        btnR2.onclick = function () {
            Animation(box, 800);
        };

        // 封装动画函数
        function Animation(ele, target) {
            // 先清除动画
            clearInterval(ele.tid);
            // 获取当前位置
            var currentLeft = ele.offsetLeft;
            // 判断左移右移
            var isLeft = (currentLeft < target);
            // 开启定时器
            ele.tid = setInterval(function () {
                // 移动
                currentLeft = isLeft ? currentLeft + 10 : currentLeft - 10;
                ele.style.left = currentLeft + "px";
                // 边界检测
                if (isLeft ? currentLeft >= target : currentLeft <= target) {
                    // 停止运动
                    clearInterval(ele.tid);
                    // 元素复位
                    ele.style.left = target + "px";
                }
            }, 50)
        }
    </script>
</body>

效果
原生js实现简单动画效果_第1张图片

匀速动画

缓速运动 : 每次移动的距离 = (目标位置 - 当前位置) / 10
特点:没有误差,准确到达目标位置后期接近目标都是1px移动 不会有误差,但还需要清除定时器 终点检测

还是上面的样式结构
js代码

<body>

    <div id="box"></div>
    <div class="line400"></div>
    <div class="line800"></div>
    
    <input type="button" value="缓速移动400" id="r1">
    <input type="button" value="缓速移动800" id="r2">

    <script>
        var box = document.getElementById("box");
        var btn1 = document.getElementById("r1");
        var btn2 = document.getElementById("r2");

        btn1.onclick = function () {
            slowMove(box, 400);
        }
        btn2.onclick = function () {
            slowMove(box, 800);
        }

        // 缓动距离方法
        function slowMove(ele, target) {
            clearInterval(ele.tid);
            // 获取元素当前位置
            var currentLeft = ele.offsetLeft;
            ele.tid = setInterval(function () {
                // 缓速速度
                var speed = (target - currentLeft) / 10;
                speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
                // 缓速移动
                currentLeft += speed;
                // 设置元素的位置
                ele.style.left = currentLeft + "px";
                // 终点检测
                if (currentLeft == 400) {
                    clearInterval(ele.tid);
                }
            }, 10)
        }

    </script>
</body>

效果:
原生js实现简单动画效果_第2张图片
以上动画方法只能实现简单的属性(带px单位)动画
要实现其他属性的动画要先了解一个获取属性的方法

getComputedStyle() : 获取元素所有样式 全局方法(IE8不支持)
参数1: 要获取样式的对象
参数2: 伪元素 ,一般不传 默认为null
返回值: 样式对象
特点:
1.可以获取行内样式,也可以获取行外样式
2.获取的是string类型 带单位
3.获取的元素只读,不可修改

ie8使用currentStyle属性
这里做一下兼容

// 获取元素属性的IE8兼容
        /**
            @param ele 需要查询的元素
            @param attr 需要获取到的属性 string类型
        */
        function getEleStyle(ele,attr){
            if(window.getComputedStyle){  // 标准
                var style = getComputedStyle(ele,null);
                return style[attr];
            }else{  // ie8
                return ele.currentStyle[attr];
            }
        }

实现多属性缓动效果封装函数

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        #box {
            width: 100px;
            height: 100px;
            background-color: pink;
            position: absolute;
            top: 100px;
            left: 0px;
        }
        #box1{
            width: 100px;
            height: 100px;
            background-color: #000;
            position: absolute;
            top: 100px;
            left: 100px;
        }
    </style>
</head>

<body>

    <div id="box"></div>
    <div id="box1"></div>

    <input type="button" value="缓速移动属性" id="r2">
    <script src="animation.js"></script>
    <script>

        var box = document.getElementById("box");
        var btn1 = document.getElementById("r1");
        var btn2 = document.getElementById("r2");

        btn2.onclick = function () {
            slowMove(box, {
                width: 200,
                height: 300
            }, function () {
                slowMove(box, {
                    width: 100,
                    height: 100
                }, function () {
                    slowMove(box, {
                        left: 200,
                        zIndex:2
                    },function(){
                        slowMove(box,{
                            opacity:0
                        },function(){
                            slowMove(box,{
                                opacity:1
                            })
                        })
                    })
                })
            });
        }

        // 缓动属性方法
        function slowMove(obj, attrs, callback) {
            clearInterval(obj.tid);
            // 开启定时器
            obj.tid = setInterval(function () {
                // 所有属性是否到达终点变量
                var isAll = true;       // 1.提出假设
                // 遍历所有属性
                for (var key in attrs) {
                    var attr = key;     // 属性名
                    var target = attrs[key]; // 属性值

                    if (attr == "zIndex" || attr == "backgroundColor") {
                        obj.style[attr] = target;
                    } else if (attr == "opacity") {
                        // 透明度是小数 不适合运算 所以扩大100倍
                        var current = parseFloat(getEleStyle(obj, attr)) * 100;
                        var speed = (target * 100 - current) / 10;
                        speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
                        current += speed;
                        obj.style[attr] = current / 100;
                        if (current != target) {
                            isAll = false;
                        }
                    } else {
                        // 获取元素当前位置 getComputedStyle方法获取到的是带单位的字符串
                        var current = parseInt(getEleStyle(obj, attr));
                        // 缓速速度 (目标位置 - 当前位置) / 10
                        var speed = (target - current) / 10;
                        speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
                        // 缓速移动
                        current += speed;
                        // 设置元素的位置
                        obj.style[attr] = current + "px";
                        // 终点检测
                        if (current != target) {    // 2.验证假设
                            isAll = false;
                        }
                    }

                }
                // 当所有属性都到达终点时再清除定时器
                if (isAll) {      // 3.根据变量结果做出操作
                    clearInterval(obj.tid);
                    // 调用回调函数
                    if (callback) {
                        setTimeout(function () {
                            callback();
                        }, 1000)
                    }
                }
            }, 10)

        }


        // 获取元素属性的IE8兼容
        /**
            @param ele 需要查询的元素
            @param attr 需要获取到的属性 string类型
        */
        function getEleStyle(ele, attr) {
            if (window.getComputedStyle) {  // 标准
                var style = getComputedStyle(ele, null);
                return style[attr];
            } else {  // ie8
                return ele.currentStyle[attr];
            }
        }
    </script>
</body>

</html>

你可能感兴趣的:(原生js)