Javascript缓动不动画

时间:2014-01-02 11:07:49

标签: javascript html css easing

尝试在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);
}

1 个答案:

答案 0 :(得分:2)

即使您在css中设置了初始值,orig_valueNaNparseFloat(el.style.marginLeft)也不会返回任何内容。即:margin-left: 15px;仍然不会返回任何内容。

您可以使用window.getComputedStyle(...).getPropertyValue,类似于:

window.getComputedStyle(el, null).getPropertyValue("margin-left");

这将为您提供实际当前值以及px,即:0px (它始终返回px中的值,即使在CSS中设置为empt

因此您需要删除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 - 使用计算样式设置动画


你很可能会做很多其他的方式,并且肯定会对这段代码进行美化,但是这应该可以让你开始。