关于做常规的数字定时滚动效果

栏目: JavaScript · 发布时间: 7年前

内容简介:目前项目团队在做一个接受到的数字要做成实现数字滚动效果 在轮询的基础上做的 就是上一个数字到目前最新的数字的变化 我想到的就是用使用setTimeout定时器那么写到这里是不是就可以简单实现了呢 其实还有一段路要走,比如你考虑了性能问题了吗上一步我们增加了防抖就是在递归调用当上一个setTimeout还存在的时候 我们要清除掉setTimeout 以免造成干扰和卡顿现象 那么是不是就可以了呢 你考虑过1秒之内setTimeout也有极限的吗 根据各个浏览器的性能差异,应该控制在20ms~30ms之间,那

目前项目团队在做一个接受到的数字要做成实现数字滚动效果 在轮询的基础上做的 就是上一个数字到目前最新的数字的变化 我想到的就是用使用setTimeout定时器

/**
* 定时器方法
* @param num {number} 当前值
* @param digitalBeating {number} 上一个值
* @param diff {number} num - digitalBeating的差值
*/
transNum(num,digitalBeating,diff) {
    let i = digitalBeating,timeout = null;
    const animate = () => {
       if (i<num) {
        i++
        timeout = setTimeout(animate,1000/diff)
       } else {
           digitalBeating = num
       }
       let numList = i.toString().split('')   // 这里是为了以数组的形式单独展示每一个数字
    }
    animate()
}
复制代码

那么写到这里是不是就可以简单实现了呢 其实还有一段路要走,比如你考虑了性能问题了吗

transNum(num,digitalBeating,diff) {
    let i = digitalBeating,timeout = null;
    const animate = () => {
       if (timeout) {
           clearTimeout(timeout)
           timeout = null
       }
       if (i<num) {
        i++
        timeout = setTimeout(animate,1000/diff)
       } else {
           digitalBeating = num
       }
       let numList = i.toString().split('')   // 这里是为了以数组的形式单独展示每一个数字
    }
    animate()
}
复制代码

上一步我们增加了防抖就是在递归调用当上一个setTimeout还存在的时候 我们要清除掉setTimeout 以免造成干扰和卡顿现象 那么是不是就可以了呢 你考虑过1秒之内setTimeout也有极限的吗 根据各个浏览器的性能差异,应该控制在20ms~30ms之间,那么我们进行下一步的改造

transNum(num,digitalBeating,diff) {
    let i = digitalBeating,timeout = null,steps = 1;
    const animate = () => {
       if (timeout) {
           clearTimeout(timeout)
           timeout = null
       }
       if (i<num) {
        if(diff<=50) {
            steps = 1
        } else if (diff=<100&&diff>50) {
            steps = 2
        } else if (diff>100&&diff<150) {
            steps = 3
        } else if ...
        
        i += steps
        timeout = setTimeout(animate,1000*steps/diff)
       } else {
           digitalBeating = num
       }
       let numList = i.toString().split('')   // 这里是为了以数组的形式单独展示每一个数字
    }
    animate()
}
复制代码

我们定义了一个变量steps作为步长来保证1秒之内调用的次数,可是以上的行为会不会很蠢 因为你没办法知道这个diff差值到底是多少 没有封顶的 所以我们继续改造

transNum(num,digitalBeating,diff) {
    let i = digitalBeating,timeout = null,len = diff.toString().length,steps = Math.pow(10,len-2);
    const animate = () => {
       if (timeout) {
           clearTimeout(timeout)
           timeout = null
       }
       if (i<num) {
        if(diff<10) {
            steps = 1
        }
        if (diff/steps>50) {
            steps *= 2
        }
        
        i += steps
        timeout = setTimeout(animate,1000*steps/diff)
       } else {
           digitalBeating = num
       }
       let numList = i.toString().split('')   // 这里是为了以数组的形式单独展示每一个数字
    }
    animate()
}
复制代码

目前来看大概就可以保证在1秒之内调用次数50次了,不过呢,你可能会发现最后一次的数字变动可能是i>num了 那么肯定就不是我们想要的结果了,就在最后一次再加个判断吧

transNum(num,digitalBeating,diff) {
    let i = digitalBeating,timeout = null,len = diff.toString().length,steps = Math.pow(10,len-2);
    const animate = () => {
       if (timeout) {
           clearTimeout(timeout)
           timeout = null
       }
       if (i<num) {
        if(diff<10) {
            steps = 1
        }
        if (diff/steps>50) {
            steps *= 2
        }
        
        i += steps
        timeout = setTimeout(animate,1000*steps/diff)
        // 这里作为最后一次判断 如果最后一次的i和num的差距小于steps时 肯定会跳过了
        if (num-i<steps) {
            i = num
        }
       } else {
           digitalBeating = num
       }
       let numList = i.toString().split('')   // 这里是为了以数组的形式单独展示每一个数字
    }
    animate()
}
复制代码

再来看看 是不是基本上能满足需求了呢 那么你能保证不会延迟吗 所以应该规定在1秒之内必须跑完了

transNum(num,digitalBeating,diff) {
    let i = digitalBeating,
    timeout = null,
    len = diff.toString().length,
    steps = Math.pow(10,len-2)
    _lastTime = new Date();   // 设置初始时间
    const animate = () => {
       if (timeout) {
           clearTimeout(timeout)
           timeout = null
       }
       let _nowTime = new Date()  // 这一轮调用时的时间
       // 在这里统一判断 
       if (i<num && num-i>=steps && _nowTime - _lastTime<1000) {
        if(diff<10) {
            steps = 1
        }
        if (diff/steps>50) {
            steps *= 2
        }
        
        i += steps
        timeout = setTimeout(animate,1000*steps/diff)
       } else {
           i = num
           clearTimeout(timeout)
           timeout = null
           digitalBeating = num
       }
       let numList = i.toString().split('')   // 这里是为了以数组的形式单独展示每一个数字
    }
    animate()
}
复制代码

唔,现在也许可行了吧 然而做了这么多 其实还是不够完美的 一个是数字滚动就不是一个数字一个数字的滚了 而且用了定时器了 这个本身就是耗费性能的事 有没有更优的办法呢 当然有 请期待用css transition 3d来实现


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Learning PHP, MySQL, and JavaScript

Learning PHP, MySQL, and JavaScript

Robin Nixon / O'Reilly Media / 2009-7-21 / USD 39.99

Learn how to create responsive, data-driven websites with PHP, MySQL, and JavaScript - whether or not you know how to program. This simple, streamlined guide explains how the powerful combination of P......一起来看看 《Learning PHP, MySQL, and JavaScript》 这本书的介绍吧!

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具