原生js实现简单匀速线性运动框架封装

正常情况下我们要写一个运动的效果会用到tween.js这么一个插件,这个东西不是一般人写出来的,因为里面涉及的运动效果都是经过一堆数学的函数运算出来的,我们平常人是写不出来的,所有我们作为js初学者可以为自己封装一个简单的(匀速线性)运动框架。涉及到复杂运动时只需改变函数中的公式即可。

如何运动:

给大家出一道题,从起点A走到目的地B,一共用了1000毫秒,每一次是30毫秒,请问你在这里面得到了哪些信息?
信息有哪些呢?

第一个,总时长是:1000毫秒

第二个,多久时间走一次?30毫秒

第三个,走的总次数:1000/30

第四个,距离:B-A

第五个,步长:距离/总次数

总结以上可以得出运动动画几要素:起始位置、结束位置、位移、运动经过的时间、元素每次移动的步长、多久时间走一步。

运动框架的实现思路:就是在一定的时间段里面改变left、top、width、height,到达目的地之后停止。

可以先思考一下,在页面里如何让div动起来?

思考如下:
1. 设置div的时候为绝对定位,因为只有绝对定位之后,left、top等值才会在页面上显示出来。否则在页面上看不见div。
2. 可以给div设置点击事件,在函数里面定义总的步数count,总距离dis,速度step=dis/count,还需要设置一个当前的步数,给它进行初始化n=0
3. 然后使用计时器setInterval(),获取到div当前的距离,让div动起来。

—单属性运动框架封装代码如下—-

    /**
         * 单属性运动框架
         */
        function animate(element, attrName, end, speed) {
            // 先清除 element 上已有的运动动画效果
            clearInterval(element.timer);
            var start = parseFloat(css(element, attrName)), // 起点
                range = end - start; // 范围
            // 启动计时器前记录起始运动时间
            var startTime = +new Date();
            // 启动计时器,开始运动
            element.timer = setInterval(function() {
                // 实际运动时间
                var elapsed = Math.min(+new Date() - startTime, speed);
                // 公式
                var result = elapsed * range / speed + start;
                // 设置css
                element.style[attrName] = result + "px";
                // 判断
                if (elapsed === speed)
                    clearInterval(element.timer);
            }, 1000/60);
        }

该函数只能改变元素单一属性,简单的来说就是不能让元素宽和移动同时改变,同时进行。

  • 示例
$("#start").onclick = function(){
            animate($("#box"), "left", 500, 3000);
        }//当点击start时,id名为box的div定位属性left在3s中变成500px;

—–多属性运动框架封装—–
通过将要改变的属性存在对象options中,来实现多属性改变:

/**
 * 运动
 * @param element 待添加运动动画效果的 DOM 元素对象
 * @param options 多属性目标终值选项
 * @param speed 限定运动的总时间
 * @param fn 在运动结束后需要继续执行的函数 
 */
function animate(element, options, speed, fn) {
    // 清除元素上已有的运动动画计时器
    clearInterval(element.timer);

    // 多属性初值、范围值
    var start = {}, range = {};
    for (var attrName in options) {
        start[attrName] = parseFloat(css(element, attrName));
        range[attrName] = options[attrName] - start[attrName];
    }

    // 记录开始运动的时间
    var startTime = +new Date();

    // 启动计时器,实现运动动画效果:将计时器 id 缓存
    element.timer = setInterval(function() {            
        // 计算已经运动的时间
        var elapsed = Math.min(+new Date() - startTime, speed);

        // 多属性按公式运算:线性运动
        for (var attrName in options) {
            // 公式:结果 = 运动时间 * 总范围 / 总时间 + 起始
            var result = elapsed * range[attrName] / speed + start[attrName];
            // 设置CSS
            element.style[attrName] = result + ("opacity" === attrName ? "" : "px");
        }

        // 判断是否停止计时器
        if (elapsed === speed) {
            clearInterval(element.timer);
            // 如果有运动结束后需要继续执行的函数,则调用函数执行
            fn && fn();
        }
    }, 1000/60);
}
  • 示例
animate($("img")[0], {width: 590,left:500}, 5000, function() {
            // animate($("img")[0], {opacity: 0}, 3000)
        });//在5s中内将img元素宽设置为590px,定位属性left设置为500px,

在该运动执行完毕后继续执行跟随function函数里面的内容(运动),可在后面依次跟随多个function来设置运动的逻辑。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值