高阶函数封装js动画

lxf2023-05-23 02:20:01

我们在生活中肯定看到过这样的场景,在我们进入页面或者刷新页面的时候数字(金额)会从高到低的一个动画效果;那么这是怎么做的呢?最开始的时候我以为是用css3来做的;后来看了别人的教程才发现,原来是用js写的;我没有完全按照教程的来,我用到的是Hz为60来计算的,教程是根据时间;大致思路是差不多的

需求分析

既然我们知道是用JS来做的,那么肯定是去变化数字了;既然我们要做到这几点,那么肯定是需要封装一些参数的

  • 时间 duration:指在此动画期间的一个事件间隔
  • from 起始值:值我们从某一个值开始动画
  • to 目标值:值这是我们最终的一个值
  • onProgress 回调函数:每次得到值以后的一个回调,便于得到数据渲染

注意:

这儿用到了window.requestAnimationFrame方法,然后在其中回调函数执行次数通常是每秒 60 次;下面代码中用到了此逻辑

代码分析

  • 将duration(毫秒)转为秒
  • 由于requestAnimationFrame有60Hz(每秒执行60次),所以将秒乘60并取整就可以得到每秒执行多少次
  • 然后dis计算出起始值和目标值差值多少
  • 差值除以每秒执行多少次,也就得到了步长
  • 在每次执行动画的时候都将得到的步长和初始值相加即可
  • 最后就是根据相对于的条件停止即可

模仿写法

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

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .number {
            font-weight: 700;
            font-size: 36px;
            width: 300px;
            margin: 100px auto;
        }
    </style>
</head>

<body>
    <div class="number"></div>
    <script>
        const number = document.querySelector('.number');
        /**
         * duration:秒
         * from:来源值
         * to:目标值
         * onProgress:回调函数
         **/
        function animation(duration, from, to, onProgress) {
            var start = new Date().getTime()
            let dur = (duration) / 1000;
            let frequency = Math.floor(dur * 60); // 每次

            const dis = to - from; // 差值
            console.log(dis);
            const speed = Math.ceil(dis / frequency); // 步长
            console.log(speed);
            let value = from; // 当前的值
            let d = from - to; // 初始值
            function _run() {
                var end = new Date().getTime()
                if (d <= to) {
                    value = to;
                    onProgress(value);
                    console.log('cost is', `${end - start}ms`)
                    return;
                };
                d = d + speed; // 相减
                value = d;
                onProgress(value);
                requestAnimationFrame(_run);
            };
            requestAnimationFrame(_run);
        };

        animation(2000,2299,299,(val)=>{
            number.innerHTML = `<span style="color:red">${val}</span>`;
        })
    </script>
</body>

</html>

网上教程

效果代码:个人感觉跟我写的差不多,数字会跑很快;感觉都都看不清了;我模仿的写法也是这样。

  • 完整代码:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .number {
            font-weight: 700;
            font-size: 36px;
            width: 300px;
            margin: 100px auto;
        }
    </style>
</head>

<body>
    <div class="number"></div>
    <script>
        const number = document.querySelector('.number');
        
        /**
         * duration:秒
         * from:来源值
         * to:目标值
         * onProgress:回调函数
         **/
        function animation(duration, from, to, onProgress) {
            const dis = to - from; // 差值
            const speed = dis / duration; // 步长
            const startTime = Date.now();
            let value = from; // 当前的值
            onProgress(value);

            function _run() {
                const now = Date.now();
                const time = now - startTime;

                if (time >= duration) {
                    value = to;
                    onProgress(value);
                    return;
                };
                const d = Math.floor(time * speed);
                value = from + d;
                onProgress(value);
                requestAnimationFrame(_run);
            };
            requestAnimationFrame(_run);
        };

        animation(1000,1099,299,(val)=>{
            number.textContent = val.toFixed(2);
        })
    </script>
</body>

</html>

修改后的效果

增加了一个判断; 如代码所示,每次执行一次动画的时候+1,执行6次以后再进行回调展示数据,就不会展示那么频繁,从而导致数据模糊效果了。

往期文章

  • css登录按钮炫酷效果

  • css是你永远学不会的语言

  • electron 中使用本地数据库

  • electron 中 webview的使用

  • 前端使用electron+vue3+ts搭建一个桌面端应用且可以热更新

  • electron+vue3+ts开发了一个JSON工具桌面软件

  • element-ui动态级联选择器回显问题,二十多行代码就可以搞定

  • 小程序云开发,通过云函数进行云开发

  • 原生js实现瀑布流效果

  • uniapp中的请求接口封装

本网站是一个以CSS、JavaScript、Vue、HTML为核心的前端开发技术网站。我们致力于为广大前端开发者提供专业、全面、实用的前端开发知识和技术支持。 在本网站中,您可以学习到最新的前端开发技术,了解前端开发的最新趋势和最佳实践。我们提供丰富的教程和案例,让您可以快速掌握前端开发的核心技术和流程。 本网站还提供一系列实用的工具和插件,帮助您更加高效地进行前端开发工作。我们提供的工具和插件都经过精心设计和优化,可以帮助您节省时间和精力,提升开发效率。 除此之外,本网站还拥有一个活跃的社区,您可以在社区中与其他前端开发者交流技术、分享经验、解决问题。我们相信,社区的力量可以帮助您更好地成长和进步。 在本网站中,您可以找到您需要的一切前端开发资源,让您成为一名更加优秀的前端开发者。欢迎您加入我们的大家庭,一起探索前端开发的无限可能!