【问题标题】:javascript smooth animation from X,Y to X1,Y1javascript从X,Y到X1,Y1的平滑动画
【发布时间】:2011-11-19 06:40:21
【问题描述】:

我想将图像(或元素)从其实际 X、Y 位置缓慢移动到 X1、Y1。

当 X 和 X1 之间的 距离 等于 与 Y 和 Y1 之间的距离时,这很容易。 但是如果 X 差异是 100px 而 Y 差异是 273px 呢?

作为 Javascript 新手,我不想重新发明轮子! 此外,由于我正在学习,我不想使用 jQuery 或类似的东西。我想要纯 JavaScript。

请提供简单的脚本:-)

【问题讨论】:

  • 我假设元素是绝对定位的......
  • @scessor 定义不纯的 JavaScript :)
  • @Šime 这就是我的意思:不纯的 javascript 不存在。
  • @epascarello Didier 不想使用 jQuery 没有问题。但是如果有人说他不想重新发明轮子,他想要一个图书馆。 jQuery 和其他的正是这个。
  • @scessor 有时候,当只是做一个简单的任务时,不需要加载一个比较大的库。

标签: javascript image animation smooth


【解决方案1】:

如果我要从头开始编写它,我会从以下内容开始:

function linearEase(start, end, percent) {
    return start + ((end - start) * percent);
}

function animateTo(settings) {
    var elem = settings.element;
    var ease = settings.ease;

    var start = { left: elem.offsetLeft, top: elem.offsetTop };

    var lastTime = new Date().getTime();
    var timeLeft = settings.totalTime;

    function update() {
        var currentTime = new Date().getTime();
        var elapsed = currentTime - lastTime;
        timeLeft -= elapsed;
        lastTime = currentTime;

        var percentDone = 1 - timeLeft/settings.totalTime;

        elem.style.top = ease(start.top, settings.top, percentDone) + "px" ;
        elem.style.left = ease(start.left, settings.left, percentDone) + "px" ;

        if(timeLeft > 0) {
            setTimeout(update, 33);
        }   
    }

    update();
}

例如,在接下来的两秒内将 div 移动到 (50,50)。

var elem = document.getElementById("animatable");

setTimeout(function() {
    animateTo({
        element: elem, 
        left: 50, 
        top: 50, 
        totalTime: 2000,
        ease: linearEase
    })
}, 10);

这是做这类事情的相当标准的模式。获取元素位置和设置样式的东西肯定可以更好地实现。但是从长远来看,抽象出一个ease 函数会让你的生活变得更轻松。我提供了一个简单的线性缓动,但其他更复杂的缓动算法将遵循相同的接口。

另外需要注意的是,超时和间隔是not guaranteed 在设定的时间运行,因此通常最好设置您希望过渡运行的总时间,然后计算出有多少时间自上次渲染以来已过去。

此外,如果您同时为一堆元素设置动画,我肯定会将其重构为单个“渲染循环”。对animateTo 的调用会将工作人员推入工作人员队列,但只有setTimeout 循环计算经过的时间然后调用每个工作人员,因此您没有大量的timeout 闭包浮动。

不管怎样,摆弄here

【讨论】:

  • 只是一个警告。 Safari 不支持ease
【解决方案2】:

在具有各种不同功能(CPU、图形处理能力、计算机上正在发生的其他事情)的系统上制作流畅的动画并非易事。正确的实现涉及开发一种有效的“补间”算法,该算法可以自适应地(随着动画运行)计算出要在动画中使用的增量,以保持进度并尽可能平滑。

做到这一点的最好方法是站在别人的肩膀上,使用以前发明的东西。在这个时代,我永远不会尝试自己从头开始写这个。它可以在 CSS3 过渡/动画中使用,但尚未在所有地方都支持。它可以在 jQuery 和 YUI3 中使用或分析。我的第一选择是使用其中一个具有丰富功能的框架。您不必将框架用于其他任何事情,如果需要,您可以将其用于动画。 YUI3 甚至可以让你构建一个代码最少的库来满足你的需求。 jQuery 一开始并不是很大。

如果您仍然坚决反对使用其中一个库,请将源代码下载到每个库的相关模块中,并研究它们是如何做到的。在每个应用程序中构建一个示例应用程序,并逐步了解它的工作原理,在有趣的地方设置断点。那将是最好的老师,向您展示如何构建一个有效的补间算法,以适应主机的速度能力。

为了让您了解补间算法如何用于直线动画(使用线性缓动),您需要对动画运行时间的动画步长值进行初始计算。这可能只是对系统可以支持什么的猜测。您将创建的步骤数划分为动画运行的时间,并为该时间量设置一个计时器,以便您知道何时运行下一步。然后,您运行一两步动画,您会看到实际经过了多少时间。如果计算机跟不上您的步数值,您将落后于计划,您将不得不适应并选择更大的步数。

现在,如果你想做一些除了线性缓动之外的事情,显然还有更多的事情要做。

Firefox 和 Chrome 还实现了一些新的实验性 API,以帮助实现流畅的动画效果。我在查看 jQuery 源代码时自己发现了这一点,因为它在可用时使用它。在 Chrome 中它被称为 webkitRequestAnimationFrame,你可以阅读它here in a Firefox blog post

【讨论】:

    【解决方案3】:

    如果您的目标是现代浏览器,CSS 过渡让生活更轻松(例如 firefox,对于其他浏览器,更改 -moz 前缀):

    <body>
        <input type="button" onclick="move()" value="press" />
        <div id="sq" style="position:absolute; top:50px; left:50px; height:50px; width:50px; background-color:Black; -moz-transition : all 0.8s ease 0s;" />
    </body>
    

    还有剧本

     function move() {
                var sq = document.getElementById("sq");
                sq.style.left = "300px";
                sq.style.top = "150px";
            }
    

    【讨论】:

      【解决方案4】:

      一种解决方案:

      function translate( elem, x, y ) {
          var left = parseInt( css( elem, 'left' ), 10 ),
              top = parseInt( css( elem, 'top' ), 10 ),
              dx = left - x,
              dy = top - y,
              i = 1,
              count = 20,
              delay = 20;
      
          function loop() {
              if ( i >= count ) { return; }
              i += 1;
              elem.style.left = ( left - ( dx * i / count ) ).toFixed( 0 ) + 'px';
              elem.style.top = ( top - ( dy * i / count ) ).toFixed( 0 ) + 'px';
              setTimeout( loop, delay );
          }
      
          loop();
      }
      
      function css( element, property ) {
          return window.getComputedStyle( element, null ).getPropertyValue( property );
      }
      

      现场演示: http://jsfiddle.net/qEVVT/1/

      【讨论】:

      • 精确! :-) 感谢分享,这正是我所看到的。
      • 这对我也有用,除了老式的 Internet Explorer。是的,我的 div 是绝对定位的。我用各种 div 元素测试了脚本/方法,但在 IE 中,没有任何动作。
      • 这就是为什么:window.getComputedStyle(element, null).getPropertyValue(property) 在 Internet Explorer 中只返回 'auto',而在所有其他浏览器中,它是一个以 'px' 结尾的数字。但我不知道如何解决这个问题。
      • 好的,我通过添加 left: 0px; 解决了我的问题到我的 div 元素。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-11-18
      • 1970-01-01
      • 1970-01-01
      • 2016-09-02
      • 1970-01-01
      • 2021-12-22
      • 2019-09-30
      相关资源
      最近更新 更多