尝试在javascript(没有jQuery)中实现简单的缓动,但不幸的是,单击按钮时似乎没有任何动画(见下文)。
我的目标是通过补间第一个项目的margin margin属性来显示隐藏列表项(最后一项)。我知道这不是CSS问题,因为手动修改样式会移动列表,但我不确定问题是什么。我的猜测是我如何调用缓动功能,但改变参数仍然不适合我。
缓和部分如下所示,整个代码在此处: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);
}
答案 0 :(得分:2)
即使您在css中设置了初始值,orig_value
为NaN
,parseFloat(el.style.marginLeft)
也不会返回任何内容。即:margin-left: 15px;
仍然不会返回任何内容。
您可以使用window.getComputedStyle(...).getPropertyValue,类似于:
window.getComputedStyle(el, null).getPropertyValue("margin-left");
这将为您提供实际当前值以及px
,即:0px
(它始终返回px
中的值,即使在CSS中设置为em
或pt
)
因此您需要删除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 - 使用计算样式设置动画
你很可能会做很多其他的方式,并且肯定会对这段代码进行美化,但是这应该可以让你开始。