JavaScript之动画函数

运动的本质

  • 通过计时器每隔一段时间移动dom元素
  • 定位

正向 终点值大于起点值

反向 终点值小于起点值

封装简易动画函数

注意函数需要传递2个参数,动画对象移动到的距离

// 封装动画函数 obj目标对象 target目标位置
function move(obj ,target){
    clearInterval(obj.timer); // 清除原有定时器

    // 元素节点本质是对象
    // 给不同元素记录不同的定时器
    obj.timer = setInterval(function () {

        if(obj.offsetLeft >= target  ){
            // 停止动画(本质是停止计时器)
            clearInterval(obj.timer);
        }
        else{
            obj.style.left = obj.offsetLeft + 50 + 'px';
        }
    },50)
}

或者

function animate(ele, end) {
        clearInterval(timer);
        var cur = ele.offsetLeft; // 元素开始的位置
        end = parseFloat(end);
        var speed = end >= cur ? 10 : -10;   // end  >  cur正向运动  

        timer = setInterval(function () {
            cur += speed;   // 每隔一段时间 在原有基础上增加对应值
            ele.style.left = cur + "px";   // 
            // 正向运动  (终点值大于起点值)
            if (Math.abs(end - cur) <= Math.abs(speed)) { // 理想情况 cur == end
                clearInterval(timer);
                ele.style.left = end + "px";
            }
        }, 20);
    }

多属性运动动画

原有封装,只能修改left不能改top,width 和height

function animate(ele, attr, end) {
        clearInterval(timer);
        // var cur = ele.offsetLeft; // 元素开始的位置
        var cur = parseFloat(getStyle(ele, attr));
        end = parseFloat(end);
        var speed = end >= cur ? 10 : -10;   // end > cur正向运动  

        timer = setInterval(function () {
            cur += speed;   // 每隔一段时间 在原有基础上增加对应值
            // ele.style.left = cur + "px";
            ele.style[attr] = cur + "px";
            // 正向运动  (终点值大于起点值)
            if (Math.abs(end - cur) <= Math.abs(speed)) { // 理想情况 cur == end
                clearInterval(timer);
                ele.style[attr] = end + "px";
            }
        }, 20)
    }


    function getStyle(ele, attr) {
        if (window.getComputedStyle) {
            return window.getComputedStyle(ele)[attr];
        } else {
            return ele.currenStyle[attr];
        }
    }

多属性运动动画之opacity

如果属性为opacity,取值时扩大100倍,赋值时,缩小100倍

function animate(ele, attr, end) {
        clearInterval(timer);
        // var cur = ele.offsetLeft; // 元素开始的位置

        if (attr == 'opacity') {   //如果是opacity  取值时扩大100倍  赋值时缩小100倍
            var cur = parseFloat(getStyle(ele, attr)) * 100;
            end = parseFloat(end) * 100;
        } else {
            var cur = parseFloat(getStyle(ele, attr));
            end = parseFloat(end);
        }

        var speed = end >= cur ? 10 : -10;   // end > cur正向运动  

        timer = setInterval(function () {
            cur += speed;   // 每隔一段时间 在原有基础上增加对应值
            // ele.style.left = cur + "px";

            // 赋值时 如果是opacity  缩小100倍;
            if (attr == "opacity") {
                ele.style[attr] = cur / 100;
            } else {
                ele.style[attr] = cur + "px";
            }

            // 正向运动  (终点值大于起点值)
            if (Math.abs(end - cur) <= Math.abs(speed)) { // 理想情况 cur == end
                clearInterval(timer);
                if (attr == "opacity") {
                    ele.style[attr] = end / 100;
                } else {
                    ele.style[attr] = end + "px";
                }
            }
        }, 20)
    }


    function getStyle(ele, attr) {
        if (window.getComputedStyle) {
            return window.getComputedStyle(ele)[attr];
        } else {
            return ele.currenStyle[attr];
        }
    }

匀速运动

speed = end >= cur ? 10 : -10

function animate(ele, attr, end) {
        clearInterval(timer);
        if (attr == "opacity") {  //如果是opacity(0-1)  取值是 扩大100倍(0-100)  赋值时缩小100倍
            var cur = parseFloat(getStyle(ele, attr)) * 100; // 传统的取值方式 + 去单位
            end = parseFloat(end) * 100;
        } else {
            // var cur = ele.offsetLeft; // 元素开始的位置(快捷取值)
            var cur = parseFloat(getStyle(ele, attr)); // 传统的取值方式 + 去单位
            end = parseFloat(end);
        }

        // 匀速运动
        var speed = 0;   // end  >  cur  正向运动

        timer = setInterval(function () {



            // 匀速运动
            // speed = end >= cur ? 10 : -10

            // 加速运动  每隔一段时间  速度有稳定的提升 v = 1/2 at^2
            // speed = speed + 1;  // 每隔10ms 速度加5
            console.log(speed);

            cur += speed;   // 每隔一段时间 在原有基础上增加对应值

            if (attr == "opacity") {
                ele.style[attr] = cur / 100;   //
            } else {
                ele.style[attr] = cur + "px";   //
            }

            // 正向运动  (终点值大于起点值)
            if (Math.abs(end - cur) <= Math.abs(speed)) { // 理想情况 cur == end
                clearInterval(timer);
                if (attr == "opacity") {
                    ele.style[attr] = end / 100;  // 到达终点
                } else {
                    ele.style[attr] = end + "px";  // 到达终点
                }
            }
        }, 10);
    }


    function getStyle(ele, attr) {
        if (window.getComputedStyle) {
            return window.getComputedStyle(ele)[attr];
        } else {
            return ele.currentStyle[attr];
        }
    }

加速运动动画效果

speed = speed + 1

每隔一段时间,速度有稳定的提升

image-20200824101048219

// 此处只能修改left   不能改 top ,width height 
    function animate(ele, attr, end) {
        clearInterval(timer);
        if (attr == "opacity") {  //如果是opacity(0-1)  取值是 扩大100倍(0-100)  赋值时缩小100倍
            var cur = parseFloat(getStyle(ele, attr)) * 100; // 传统的取值方式 + 去单位
            end = parseFloat(end) * 100;
        } else {
            // var cur = ele.offsetLeft; // 元素开始的位置(快捷取值)
            var cur = parseFloat(getStyle(ele, attr)); // 传统的取值方式 + 去单位
            end = parseFloat(end);
        }

        // 匀速运动   
        var speed = 0;   // end  >  cur  正向运动  

        timer = setInterval(function () {



            // 匀速运动
            // speed = end >= cur ? 10 : -10

            // 加速运动  每隔一段时间  速度有稳定的提升 v = 1/2 at^2
           speed = speed + 1;  // 每隔10ms 速度加5
            console.log(speed);

            cur += speed;   // 每隔一段时间 在原有基础上增加对应值

            if (attr == "opacity") {
                ele.style[attr] = cur / 100;   // 
            } else {
                ele.style[attr] = cur + "px";   // 
            }

            // 正向运动  (终点值大于起点值)
            if (Math.abs(end - cur) <= Math.abs(speed)) { // 理想情况 cur == end
                clearInterval(timer);
                if (attr == "opacity") {
                    ele.style[attr] = end / 100;  // 到达终点
                } else {
                    ele.style[attr] = end + "px";  // 到达终点
                }
            }
        }, 10);
    }


    function getStyle(ele, attr) {
        if (window.getComputedStyle) {
            return window.getComputedStyle(ele)[attr];
        } else {
            return ele.currentStyle[attr];
        }
    }

缓动动画效果

缓动动画就是让元素运动速度有所变化,最常见的是让速度慢慢停下来

  • 让盒子每次移动的距离慢慢变小,速度就会慢慢落下来
  • 核心算法:(目标值-现在的位置)/ 缓冲因子 作为每次移动的距离步长
  • 缓冲因子一般为8-12
  • 停止的条件是:让当前盒子位置等于目标位置就停止定时器
  • 注意步长值是需要取整的

缓冲运动的问题

a.速度不断递减无限接近0,但是不等于0,运动的元素无限接近0

​ 正向运动(终点值>起点值) 速度是正值

​ 反向运动(终点值<起点值) 速度是负值

speed = (end-current)/10

  // 如果step大于0为正值,则往大了取,向上取整
var step = Math.ceil((target - obj.offsetLeft) / 10);

// 如果step小于0位负值,则往小了取,向下取整
var step = Math.floor((target - obj.offsetLeft) / 10);

// 即
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) :Math.floor(step);

匀速动画就是 盒子是当前的位置+固定的值

缓动动画就是 盒子当前的位置+变化的值(目标值-现在的位置)/10)

// 缓动动画

// 封装动画函数 obj目标对象 target目标位置
function move(obj ,target){
    clearInterval(obj.timer); // 清除原有定时器

    // 获得盒子的当前位置
    obj.timer = setInterval(function () {

        // 步长值写到定时器的里面
        var step = (target - obj.offsetLeft) / 10;

        if(obj.offsetLeft = target  ){
            // 停止动画(本质是停止计时器)
            clearInterval(obj.timer);
        }
        else{
            // 把每次加50 这个布长值,改为一个慢慢变小的值 布长公式:(目标值-现在的位置) / 10
            obj.style.left = obj.offsetLeft + step + 'px';
        }
    },15)
}

链式运动

运动结束之后,可以执行其他的操作(原理 接收一个回调函数,结束时调用)

动画函数添加回调函数

回调函数原理:函数可以作为一个参数。将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,再执行传进去的这个函数,这个过程就叫做回调

  • 回调函数写的位置:定时器结束的位置

封装步骤总结

  • 原生手写,正向运动和反向运动
  • 封装成简易运动函数 offsetLeft
  • 封装成多属性运动 let/top/width/height
  • 封装成多属性运动 => opacity

  • 加速运动/缓冲运动 => 多类型运动
  • 多元素运动 ele.timer
  • 链式运动(运动结束之后,执行回调函数)
  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值