javascript javascript从X,Y到X1,Y1的平滑动画
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7454983/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
javascript smooth animation from X,Y to X1,Y1
提问by Didier Levy
I'd like to sloothly move an image (or an element) from its actual X, Y location to X1, Y1.
我想缓慢地将图像(或元素)从其实际 X、Y 位置移动到 X1、Y1。
When the distancebetween X and X1 is equalto that between Y and Y1 its easy. But what if the X difference is say 100px and Y diff is 273px?
当X 和 X1 之间的距离等于Y 和 Y1 之间的距离时,它很容易。但是如果 X 差异是 100px 而 Y 差异是 273px 呢?
Being new to Javascript, I don't want to re-invent the wheel! Besides, since I'm learning, I do NOT want to use jQuery or the likes. I want pure javascript.
作为 Javascript 的新手,我不想重新发明轮子!此外,由于我正在学习,我不想使用 jQuery 或类似的东西。我想要纯 javascript。
Please supply with simple script :-)
请提供简单的脚本:-)
回答by ?ime Vidas
One solution:
一种解决方案:
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 );
}
Live demo:http://jsfiddle.net/qEVVT/1/
现场演示:http : //jsfiddle.net/qEVVT/1/
回答by jfriend00
Doing smooth animation on systems with a variety of different capabilities (CPU, graphics power, other things going on on the computer) is not a trivial task. A proper implementation involves developing an effective "tweening" algorithm that can figure out adaptively (as the animation runs) what increments to be using in the animation in order to stay on schedule and be as smooth as possible.
在具有各种不同功能(CPU、图形能力、计算机上发生的其他事情)的系统上制作流畅的动画并不是一项简单的任务。正确的实现涉及开发一种有效的“补间”算法,该算法可以自适应地(在动画运行时)确定动画中使用的增量,以便按计划进行并尽可能平滑。
The best way to do this is to stand on the shoulders of others and use what has been invented before. In this day and age, I would never try to write this myself from scratch. It's there to use in CSS3 transitions/animations, but those aren't yet supported everywhere. It's there to use or analyze in jQuery and YUI3. My first choice would be to use one of the frameworks that has a rich set of capabilities here. You don't have to use the framework for anything else, you can just use it for the animation if you want. YUI3 will even let you construct a library that has the least code in it possible for just what you want. jQuery isn't very big to start with.
做到这一点的最好方法是站在别人的肩膀上,使用以前发明的东西。在这个时代,我永远不会尝试自己从头开始写这个。它可用于 CSS3 过渡/动画,但尚未在所有地方支持。它可以在 jQuery 和 YUI3 中使用或分析。我的第一选择是在这里使用具有丰富功能的框架之一。您不必将框架用于其他任何事情,如果需要,您可以将其用于动画。YUI3 甚至可以让您构建一个库,其中包含尽可能少的代码来满足您的需求。jQuery 一开始并不是很大。
If you're still dead set against using one of the libraries, then download the source to the relevant modules for each library and study how they do it. Build a sample app in each and step through how it works, setting breakpoints at interesting spots. That will be the best teacher and show you how to build an effective tweening algorithm that can adapt to the speed capabilities of the host computer.
如果您仍然坚决反对使用其中一个库,那么将源代码下载到每个库的相关模块并研究它们是如何做到的。在每个应用程序中构建一个示例应用程序并逐步了解它的工作原理,在有趣的地方设置断点。那将是最好的老师,并向您展示如何构建可以适应主机速度能力的有效补间算法。
To give you an idea of how a tweening algorithm works for a straight animation (with linear easing), you make an initial calculation of what you want your animation step value to be for the time you want the animation to run. This is probably just a guess as to what the system can support. You divide the number of steps that creates into the time the animation runs and you set a timer for that amount of time so you know when to run the next step. You then run one or two steps of the animation and you see how much time has actually elapsed. If the computer can't keep up with your step value, you will be behind schedule and you will have to adapt and pick a larger step.
为了让您了解补间算法如何用于直线动画(使用线性缓动),您需要对动画运行时间的动画步长值进行初始计算。这可能只是对系统可以支持的内容的猜测。您将创建的步骤数除以动画运行的时间,然后为该时间量设置一个计时器,以便您知道何时运行下一步。然后运行一两步动画,您会看到实际过去了多少时间。如果计算机跟不上您的步长值,您将落后于计划,您将不得不适应并选择更大的步长。
Now, if you want to do something other than linear easing, there's obviously even more involved.
现在,如果你想做一些线性缓动以外的事情,显然还有更多的事情要做。
Firefox and Chrome have also implemented some new experiemental APIs to help with smooth animation. I discovered this myself when looking at the jQuery source because it uses it when it's available. In Chrome it's called webkitRequestAnimationFrame and you can read about it here in a Firefox blog post.
Firefox 和 Chrome 还实现了一些新的实验性 API,以帮助实现流畅的动画效果。我在查看 jQuery 源代码时自己发现了这一点,因为它在可用时使用它。在 Chrome 中,它被称为 webkitRequestAnimationFrame,您可以在 Firefox 博客文章中阅读有关它的信息。
回答by Alejandro Martin
If you are targeting modern browsers, CSS transitions make the life easier (Example for firefox, for other browsers, change the -moz prefix):
如果你的目标是现代浏览器,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>
And the script
还有剧本
function move() {
var sq = document.getElementById("sq");
sq.style.left = "300px";
sq.style.top = "150px";
}
回答by J. Holmes
If I was going to write it from scratch I would start with something like this:
如果我要从头开始编写它,我会从这样的事情开始:
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();
}
For example, to move a div to (50,50) over the next two seconds.
例如,在接下来的两秒内将 div 移动到 (50,50)。
var elem = document.getElementById("animatable");
setTimeout(function() {
animateTo({
element: elem,
left: 50,
top: 50,
totalTime: 2000,
ease: linearEase
})
}, 10);
Which is a fairly standard pattern for doing this kind of stuff. Getting the element position and setting the style stuff could be better implemented for sure. But abstracting out an ease
function will make your life a lot easier in the long run. I've provided a simple linear ease, but other more complicated easing algorithms would abide by that same interface.
这是做这种事情的一个相当标准的模式。获取元素位置和设置样式的东西肯定可以更好地实现。但是从ease
长远来看,抽象出一个函数会让你的生活更轻松。我提供了一个简单的线性缓动,但其他更复杂的缓动算法将遵循相同的接口。
Another thing to note is that timeouts and intervals are not guaranteedto run at a set time, so its usually best to set the total time that you want the transition to take to run, and then figure out how much time has elapsed since the last time you rendered.
另一件要注意的事情是,不能保证超时和间隔在设定的时间运行,因此通常最好设置您希望转换运行的总时间,然后计算自上次以来已经过去了多少时间你渲染的时间。
Also if you are animating a bunch of elements at once, I would definitely refactor this to a single "render loop". calls to the animateTo
would push workers into a queue of workers, but only have setTimeout
loop that calculates the time elapsed then invokes each worker, so you don't have a bazillion timeout
closures floating around.
此外,如果您一次为一堆元素设置动画,我肯定会将其重构为单个“渲染循环”。对 的调用animateTo
会将工作人员推入工作人员队列,但只有setTimeout
循环计算经过的时间,然后调用每个工作人员,因此您不会有无数个timeout
闭包。
Anyway, fiddle here
无论如何,在这里摆弄