简体   繁体   English

JavaScript缓动不动画

[英]Javascript easing not animating

Trying to implement simple easing in javascript (without jQuery) but unfortunately there doesn't seem to be any animation when the button is clicked (see below). 试图在javascript中实现简单的缓动(不使用jQuery),但是不幸的是,单击按钮时似乎没有任何动画(请参见下文)。

My goal is to get the hidden list item (the last item) visible by tweening the first item's margin left property. 我的目标是通过补间第一项的margin left属性来使隐藏的列表项(最后一项)可见。 I know it isn't a CSS issue because manually modifying the style moves the list, but I'm not sure what the issue is. 我知道这不是CSS问题,因为手动修改样式会移动列表,但是我不确定是什么问题。 My guess is with how I'm calling the ease function but changing the params still wasn't working for me. 我的猜测是我如何调用缓动函数,但是更改参数仍然对我不起作用。

The easing part is below, entire code is here: Fiddle 缓动部分在下面,整个代码在这里: 小提琴

JS: 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);
}

Your orig_value is NaN as parseFloat(el.style.marginLeft) returns nothing, even if you set an initial value in the css. 您的orig_valueNaN因为parseFloat(el.style.marginLeft)不会返回任何内容,即使您在CSS中设置了初始值也是如此。 ie: margin-left: 15px; 即: margin-left: 15px; still will return nothing. 仍然不会返回任何东西。

You can use window.getComputedStyle(...).getPropertyValue , similar to this: 您可以使用window.getComputedStyle(...)。getPropertyValue ,类似于:

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

This will give you the actual current value along with the px , ie: 0px . 这将为您提供实际的当前值以及px ,即: 0px
(It always return the value in px even if set in CSS as em or pt ) (即使在CSS中将其设置为empt它也始终以px返回值)

So you need to remove the px and the get the float value. 因此,您需要删除px并获取float值。

You can wrap this into a little helper similar to this: 您可以将其包装到一个类似于以下内容的小帮手中:

getElementMarginLeftAsFloat = function (el) {
    var pxValue = window.getComputedStyle(el, null).getPropertyValue("margin-left");
    var valueOnly = pxValue.substring(0, pxValue.length - 2);

    return parseFloat(valueOnly);
}

Another issue is that the moving of the actual element occurs within setTimeout executed inside a loop. 另一个问题是实际元素的移动发生在循环内执行的setTimeout The loop which calls setTimeout , causes each setTimeout to be queued nearly simultaneously, hence they all execute close to the same time, causing the element to just jump. 调用setTimeout的循环使每个setTimeout几乎同时排队,因此它们都在接近同一时间执行,从而导致元素刚刚跳转。

You can use a recursive sub-method inside your method which uses setTimeout to call itself until it is done. 您可以在方法内部使用递归子方法,该方法使用setTimeout自行调用,直到完成。 That way each setTimeout is triggered only after the specified interval, causing them to be executed close enough apart to the specified interval, similar to this: 这样,每个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();
};

By having the setTimeout function call itself, it releases the resources, ensuring the drawing of the element can occur between each "iteration". 通过让setTimeout函数调用自身,它可以释放资源,从而确保可以在每个“迭代”之间进行元素绘制。

I updated your code to use this approach and it seems to work now. 我更新了您的代码以使用这种方法,现在看来可以了。


DEMO - animating movement using computed style 演示 -使用计算样式对运动进行动画处理


You can most likely do this many other ways and also prettify this code for sure but but this should get you started either way. 您很可能可以通过许多其他方式执行此操作,并且可以肯定地美化此代码,但这可以使您开始使用这两种方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM