我想将图像(或元素)从实际的X,Y位置倾斜移动到X1,Y1。
当X和X1 之间的距离等于时,Y和Y1之间的距离很容易。 但是,如果X差异是100px而Y diff是273px怎么办?
刚接触Javascript,我不想重新发明轮子! 此外,因为我正在学习,我不想使用jQuery或类似的东西。我想要纯粹的javascript。
请提供简单的脚本: - )
答案 0 :(得分:7)
一个解决方案:
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 );
}
答案 1 :(得分:3)
在具有各种不同功能(CPU,图形处理能力,计算机上正在发生的其他事情)的系统上进行平滑动画并非易事。正确的实现涉及开发一种有效的“补间”算法,该算法可以自适应地计算(当动画运行时)在动画中使用的增量,以便保持按计划并尽可能平滑。
这样做的最好方法是站在别人的肩膀上,并使用之前发明的东西。在这个时代,我永远不会尝试从头开始写这个。它可以在CSS3过渡/动画中使用,但到处都不支持。它可以在jQuery和YUI3中使用或分析。我的第一选择是使用其中一个具有丰富功能的框架。您不必将框架用于其他任何内容,如果需要,您可以将其用于动画。 YUI3甚至可以让你构建一个代码最少的库,可以满足你的需要。 jQuery起初并不是很大。
如果您仍然没有使用其中一个库,请将源代码下载到每个库的相关模块,并研究它们是如何进行的。在每个应用程序中构建一个示例应用程序并逐步完成它的工作原理,在有趣的位置设置断点这将是最好的老师,并向您展示如何构建一个有效的补间算法,以适应主机的速度功能。
为了让您了解补间算法如何适用于直线动画(使用线性缓动),您可以初步计算您希望动画步长值在您希望动画运行的时间。这可能只是猜测系统可以支持什么。您将创建的步数除以动画运行的时间,并为该时间量设置计时器,以便知道何时运行下一步。然后运行动画的一个或两个步骤,您会看到实际经过了多长时间。如果计算机无法跟上您的步数,您将落后于计划,您将不得不适应并选择更大的步骤。
现在,如果你想做除线性宽松之外的其他事情,那么显然会涉及更多。
Firefox和Chrome还实施了一些新的体验式API来帮助平滑动画。我在查看jQuery源代码时发现了这一点,因为它在可用时使用它。在Chrome中,它被称为webkitRequestAnimationFrame,您可以阅读它here in a Firefox blog post。
答案 2 :(得分:1)
如果您的目标是现代浏览器,那么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";
}
答案 3 :(得分:0)
如果我要从头开始编写,我会从这样开始:
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