只迭代每一个元素

时间:2015-08-02 12:10:08

标签: javascript jquery html css3 css-animations

我有通过CSS3动画制作的元素列表,如下所示:

.anim-slide-left {
    animation: anim-slide-left 0.8s ease forwards;
    -webkit-animation: anim-slide-left 0.8s ease forwards;

}
@-webkit-keyframes anim-slide-left {
    0% {
        transform: translateX(-500px);
        -webkit-transform: translateX(-500px);
        opacity: 0;
    }
    100% {
        transform: translateX(0);
        -webkit-transform: translateX(0);
        opacity: 1;
    }
}

/* there are more, but very similar */

当页面加载时,js应仅为具有特殊类别的可见元素设置动画'动画':

$(function() {

    var $window = $(window);
    var $toAnimate = $('.animate');
    animate();

        // check if element is on the viewport
    function isElementVisible(elementToBeChecked)
    {
        var TopView = $(window).scrollTop();
        var BotView = TopView + $(window).height();
        var TopElement = elementToBeChecked.offset().top;
        return ((TopElement <= BotView) && (TopElement >= TopView));
    }
        // add css animation class
    function animate()
    {
        $toAnimate.each(function(i, el)
        {
            var $el = $toAnimate.eq(i);

            if ($el.length && isElementVisible($el))
            {
                    // remove already visible elements
                $toAnimate.splice(i, 1);

                    // setting up animation effect
                $el.addClass( $el.data('effect') );

                $el.removeClass('animate');
            } 
        });
    }
});

现在问题就在于此。只检查每个第二个元素是否可见,如下所示:

collections.defaultdict

但它应该是这样的:

enter image description here

仅当页面向下滚动时,其他元素才会生成动画,其中包含:

$window.scroll( function()
{
    animate();
});

如何遍历此场景中的每个元素?

编辑:

注意@ T.J。 Crowder评论我用@charlietfl建议的过滤函数修改了animate函数:

$('.animate').filter( function( idx ) {
    if( isElementVisible($(this)) )
    {
        $(this).addClass( $(this).data('effect') );
        $(this).removeClass('animate');
    }
});

它工作得很好:)谢谢你们。

2 个答案:

答案 0 :(得分:5)

那里有几个问题:

  1. 您正在修改您正在迭代的集合($toAnimate),并且您正在使用不断增加的索引从该集合中检索项目。所以很自然地,如果你删除一个,从那时起你的索引就会被关闭。

  2. splice不是官方的jQuery方法。它没有记录,可能随时消失。 (jQuery对象不是数组;它们只是类似数组。)

  3. 据我所知,jQuery会no guarantees关于each如果你在迭代的集合中添加或删除条目会做什么(不像JavaScript& #39; s forEach)。

  4. 由于您拥有splice和来自forEach的迭代保证,因此您可以使用.get$toAnimate设为实际数组:

    var $toAnimate = $('.animate').get();
    // ---------------------------^^^^^^
    

    ......然后:

    function animate()
    {
        $toAnimate.forEach(function(el)
        {
            var $el = $(el);
            if (isElementVisible($el))
            {
                // remove already visible elements
                $toAnimate.splice(i, 1);
    
                // setting up animation effect
                if( $el.data('effect') == 'anim-bar' ) animateBar($el);
                else $el.addClass( $el.data('effect') );
    
                $el.removeClass('animate');
            } 
        });
    }
    

答案 1 :(得分:1)

您正在从正在迭代的数组中删除项目,因此下一个项目将取代当前项目。当您转到下一个项目时,将跳过一个项目。

如果从最后循环遍历数组,删除项目不会影响循环中的项目:

function animate()
{
    for (var i = $toAnimate.length - 1; i >= 0; i--)
    {
        var $el = $toAnimate.eq(i);

        if ($el.length && isElementVisible($el))
        {
                // remove already visible elements
            $toAnimate.splice(i, 1);

                // setting up animation effect
            if( $el.data('effect') == 'anim-bar' ) animateBar($el);
            else $el.addClass( $el.data('effect') );

            $el.removeClass('animate');
        } 
    });
}