JS 缓动动画原理

简介: JS 缓动动画原理

所谓的缓动动画就是在动画的基础上,使元素的速度缓慢增加或缓慢减小的过程(减速或加速),那它使得盒子速度缓慢减小的原理是什么呢??很简单,可以理解为定时器每次进行一次,都执行:当前的距离+变化的步长,首先我们需要一个公式:


这个公式就是每次当前距离要加 的 不断变化的步长,我们称其为步长公式:(目标值-当前位置)/ 10  (这个10可以改)


步长公式的理解:

第一次增加的步长:


假设目标值为到 800px 时停止




第二次增加的步长:




第三次增加的步长:



后面的几步同理以此类推,达到了步长递减的效果,从而达到减速的效果,当距离左边的距离等于目标距离时清除定时器停止即可。


一:代码案例:

让盒子不断减速到目标位置800px处,如图所示:






JS实现:

<script>

       document.addEventListener('DOMContentLoaded',function(){

           var box=document.querySelector('div');

           var btn=document.querySelector('button');

           function run(obj,long){

               clearInterval(obj.timer)

               obj.timer=setInterval(function(){

                   if(obj.offsetLeft==long){  //左边距离与目标距离一样时就停止(清除定时器)

                       window.clearInterval(obj.timer);

                   }else{

                       step=(long-box.offsetLeft)/10  //步长公式

                       obj.style.left=obj.offsetLeft+step+'px';

                   }

               },20)

           }

           btn.addEventListener('click',function(){

                run(box,800)

           })

       })

   </script>




但是这样还是存在一个弊端,就是我们目标是停在800px处,但我们可以看到却停在了795.5px,这是因为我们求步长时存在除不尽取小数的问题,这时要解决这个问题我们就要采取:向上转型(Math.ceil)即可


改进代码:

<script>

       document.addEventListener('DOMContentLoaded',function(){

           var box=document.querySelector('div');

           var btn=document.querySelector('button');

           function run(obj,long){

               clearInterval(obj.timer)

               obj.timer=setInterval(function(){

                   if(obj.offsetLeft==long){

                       window.clearInterval(obj.timer);

                   }else{

                       step=Math.ceil((long-box.offsetLeft)/10)

                       obj.style.left=obj.offsetLeft+step+'px';

                   }

               },20)

           }

           btn.addEventListener('click',function(){

                run(box,800)

           })

       })

   </script>




这样就可以得到和目标值一样的移动距离啦 !


案例补充说明:

其次,我们这个案例用了步长公式就可以完成向后退的效果了,原理是得到了负的 step 值,这样当前距离 + 步长其实是一个减法,就可以往回退了,这里同样还是要注意小数转型的问题,刚才正步长相加是向上转型,现在减负步长我们要使用向下转型。这里我们可以增加一个三元运算符判断步长正负来选择使用向上还是向下转型: step=step>0?Math.ceil(step):Math.floor(step)


<body>

   <script>

       document.addEventListener('DOMContentLoaded',function(){

           var box=document.querySelector('div');

           var btn800=document.querySelector('.go800');

           var btn500=document.querySelector('.go500');

           function run(obj,long){

               clearInterval(obj.timer)

               obj.timer=setInterval(function(){

                   if(obj.offsetLeft==long){

                       window.clearInterval(obj.timer);

                   }else{

                       step=(long-box.offsetLeft)/10

                       step=step>0?Math.ceil(step):Math.floor(step)  //判断步长正负来选择使用哪个转型

                       obj.style.left=obj.offsetLeft+step+'px';

                   }

               },20)

           }

           btn500.addEventListener('click',function(){

               run(box,500)

           })

           btn800.addEventListener('click',function(){

                run(box,800)

           })

       })

   </script>

    <div></div>

    <button class="go800">到800</button>

    <button class="go500">到500</button>

</body>


以上问题就可以得到完美解决!!


二:下一个问题是给缓动动画添加回调函数,简单的目标效果是当定时器停止,即盒子到达目标位置后,让盒子变色或其他效果,这时就需要我们添加回调函数啦

我们要在调用 动画函数 的参数里添加一个 变色回调函数 作为实参(以第一个动画函数调用为例)


//第一个动画函数的调用

btn500.addEventListener('click',function(){

               run(box,500,function(){

                   box.style.backgroundColor='red';

               })

           })

然后动画函数的形参需要有一个值来接收,我们命名该形参为 callback,接收后当函数调用时相当于执行了一步:callback=function(){},然后因为我们目标是在停下之后变色,所以这个函数的调用应该放在定时器结束判断条件之后


if(callback){     //如果有回调函数实参传入,就执行回调函数,没有就不执行

      callback();

}

完整代码为:

<body>

   <script>

       document.addEventListener('DOMContentLoaded',function(){

           var box=document.querySelector('div');

           var btn800=document.querySelector('.go800');

           var btn500=document.querySelector('.go500');

           var btn0=document.querySelector('.go0')

           function run(obj,long,callback){

               clearInterval(obj.timer)

               obj.timer=setInterval(function(){

                   if(obj.offsetLeft==long){

                       window.clearInterval(obj.timer);

                       if(callback){

                       callback();

                   }

                   }else{

                       step=(long-box.offsetLeft)/10

                       step=step>0?Math.ceil(step):Math.floor(step)

                       obj.style.left=obj.offsetLeft+step+'px';

                   }

               },20)

           }

           btn500.addEventListener('click',function(){

               run(box,500,function(){

                   box.style.backgroundColor='red';

               })

           })

           btn800.addEventListener('click',function(){

                run(box,800)

           })

           btn0.addEventListener('click',function(){

               run(box,0)

           })

       })

   </script>

    <div></div>

    <button class="go800">到800</button>

    <button class="go500">到500</button>

    <button class="go0">到原位</button>

</body>


相关文章
|
9月前
|
机器学习/深度学习 JavaScript 前端开发
JS进阶教程:递归函数原理与篇例解析
通过对这些代码示例的学习,我们已经了解了递归的原理以及递归在JS中的应用方法。递归虽然有着理论升华,但弄清它的核心思想并不难。举个随手可见的例子,火影鸣人做的影分身,你看到的都是同一个鸣人,但他们的行为却能在全局产生影响,这不就是递归吗?雾里看花,透过其间你或许已经深入了递归的魅力之中。
361 19
|
自然语言处理 JavaScript 前端开发
深入理解JavaScript中的闭包:原理与实战
【10月更文挑战第12天】深入理解JavaScript中的闭包:原理与实战
|
JavaScript 前端开发
如何使用时间切片来优化JavaScript动画的性能?
如何使用时间切片来优化JavaScript动画的性能?
496 158
|
JavaScript 前端开发
如何在不影响性能的前提下使用JavaScript库来实现复杂的动画效果?
如何在不影响性能的前提下使用JavaScript库来实现复杂的动画效果?
571 156
|
JavaScript 前端开发
CSS3 动画和 JavaScript 动画的性能比较
具体的性能表现还会受到许多因素的影响,如动画的复杂程度、浏览器的性能、设备的硬件条件等。在实际应用中,需要根据具体情况选择合适的动画技术。
463 154
|
JavaScript 前端开发 Java
深入理解 JavaScript 中的 Array.find() 方法:原理、性能优势与实用案例详解
Array.find() 是 JavaScript 数组方法中一个非常实用和强大的工具。它不仅提供了简洁的查找操作,还具有性能上的独特优势:返回的引用能够直接影响原数组的数据内容,使得数据更新更加高效。通过各种场景的展示,我们可以看到 Array.find() 在更新、条件查找和嵌套结构查找等场景中的广泛应用。 在实际开发中,掌握 Array.find() 的特性和使用技巧,可以让代码更加简洁高效,特别是在需要直接修改原数据内容的情形。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一
|
监控 JavaScript 前端开发
MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver:原理与实战案例
MutationObserver 是一个非常强大的 API,提供了一种高效、灵活的方式来监听和响应 DOM 变化。它解决了传统 DOM 事件监听器的诸多局限性,通过异步、批量的方式处理 DOM 变化,大大提高了性能和效率。在实际开发中,合理使用 MutationObserver 可以帮助我们更好地控制 DOM 操作,提高代码的健壮性和可维护性。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver:原理与实战案例
|
JavaScript 前端开发 Java
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
柯里化是一种强大的函数式编程技术,它通过将函数分解为单参数形式,实现了灵活性与可复用性的统一。无论是参数复用、延迟执行,还是函数组合,柯里化都为现代编程提供了极大的便利。 从 Redux 的选择器优化到复杂的数据流处理,再到深度嵌套的函数优化,柯里化在实际开发中展现出了非凡的价值。如果你希望编写更简洁、更优雅的代码,柯里化无疑是一个值得深入学习和实践的工具。从简单的实现到复杂的应用,希望这篇博客能为你揭开柯里化的奥秘,助力你的开发之旅! 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一
|
前端开发 API 开发者
Next.js 实战 (五):添加路由 Transition 过渡效果和 Loading 动画
这篇文章介绍了Framer Motion,一个为React设计的动画库,提供了声明式API处理动画和页面转换,适合创建响应式用户界面。文章包括首屏加载动画、路由加载Loading、路由进场和退场动画等主题,并提供了使用Framer Motion和next.js实现这些动画的示例代码。最后,文章总结了这些效果,并邀请读者探讨更好的实现方案。
414 0
Next.js 实战 (五):添加路由 Transition 过渡效果和 Loading 动画
|
JavaScript 前端开发 API
Vue.js响应式原理深度解析:从Vue 2到Vue 3的演进
Vue.js响应式原理深度解析:从Vue 2到Vue 3的演进
449 17