试图在 javascript(没有 jQuery)中实现简单的缓动,但不幸的是,当按钮被点击时似乎没有任何动画(见下文)。
我的目标是通过补间第一项的 margin left 属性使隐藏的列表项(最后一项)可见。我知道这不是 CSS 问题,因为手动修改样式会移动列表,但我不确定问题出在哪里。我的猜测是我如何调用 ease 函数,但更改参数仍然对我不起作用。
下面是缓动部分,完整代码在这里:Fiddle
JS:
var start = document.getElementById('start'),
list = document.getElementById('my-list'),
imgs = list.getElementsByTagName('img'),
last_img = imgs[imgs.length -1 ];
ease = function(t, b, c, d) {
if ((t/=d/2) < 1) return c/2*t*t + b;
return -c/2 * ((--t)*(t-2) - 1) + b;
},
shift_imgs = function(el) {
var orig_value = parseFloat( el.style.marginLeft ),
end_value = -37,
change = Math.abs( end_value - orig_value ),
duration = 1, // 1 second
time = 0;
for ( var i = 0; i < change; i++ ) {
setTimeout(function() {
el.style.marginLeft = ( parseFloat( el.style.marginLeft ) + 1 ) + 'px';
}, time);
time = ease(time, orig_value, change, duration);
}
};
start.onclick = function() {
shift_imgs(last_img);
}
最佳答案
您的 orig_value
是 NaN
因为 parseFloat(el.style.marginLeft)
不返回任何内容,即使您在 css 中设置了初始值.即:margin-left: 15px;
仍然不会返回任何内容。
您可以使用 window.getComputedStyle(...).getPropertyValue ,类似这样:
window.getComputedStyle(el, null).getPropertyValue("margin-left");
这将为您提供实际的当前值以及 px
,即:0px
。
(即使在 CSS 中设置为 em
或 pt
,它始终以 px
返回值)
因此您需要删除 px
并获取浮点值。
你可以把它包装成一个类似这样的小助手:
getElementMarginLeftAsFloat = function (el) {
var pxValue = window.getComputedStyle(el, null).getPropertyValue("margin-left");
var valueOnly = pxValue.substring(0, pxValue.length - 2);
return parseFloat(valueOnly);
}
另一个问题是实际元素的移动发生在循环内执行的 setTimeout
内。调用 setTimeout
的循环导致每个 setTimeout
几乎同时排队,因此它们几乎同时执行,导致元素跳转。
您可以在您的方法中使用递归子方法,该方法使用 setTimeout
调用自身直到完成。这样每个 setTimeout
仅在指定的时间间隔后被触发,导致它们在指定的时间间隔内足够接近地执行,类似于此:
shift_imgs = function (el) {
var orig_value = getElementMarginLeftAsFloat(el),
end_value = -37,
change = Math.abs(end_value - orig_value),
duration = 1, // 1 second
time = 0;
function doShift() {
currentValue = getElementMarginLeftAsFloat(el);
if(currentValue+1 > change){
return;
};
el.style.marginLeft = (currentValue + 1) + 'px';
time = ease(time, orig_value, change, duration);
setTimeout(doShift, time);
}
doShift();
};
通过调用 setTimeout
函数自身,它释放资源,确保元素的绘制可以在每次“迭代”之间进行。
我更新了您的代码以使用这种方法,它现在似乎可以工作了。
DEMO - 使用计算样式动画运动
您很可能可以通过许多其他方式执行此操作,并且肯定会美化此代码,但这应该让您以任何一种方式开始。
关于Javascript 缓动而不是动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20881579/