触发器内包含动画的循环未能正常工作

3

我似乎遇到了一点困难。我正在制作一个带有图像滑块的页面。滑块有三个图像,一个位于屏幕中央,另外两个溢出到左右两侧。当你点击按钮以推进幻灯片时,它会运行以下代码...

$('#slideRight').click(function() {
    if ($('.container').is(':animated')) {return false;}
    var next=parseInt($('.container img:last-of-type').attr('id')) + 1;
    if (next == 12) {
        next = 0;
    }
    var diff = galsize() - 700;
    if ($('.thumbs').css("left") == "0px") {
        var plus = 78;
    } else {
        var plus = 0;
    }
    var app='<img id="' + next + '" src="' + imgs[next].src + '">';
    $('.container').width('2800px').append(app);
    $('.container').animate({marginLeft: (diff + plus) + "px"}, 300, function() {
        $('.container img:first-of-type').remove();
        $('.container').width('2100px').css("margin-left", (galsize() + plus) + "px");
    });
}); // end right click

这个很好,没有问题......我还设置了一个间隔,每5秒自动运行,形成幻灯片......

var slideShow = setInterval(function() {
    $('#slideRight').trigger("click");
}, 5000);

这也完美地运行,没有问题... 但我的问题是... 当你点击缩略图时,它应该运行此代码,直到当前图片与缩略图相同... 这是代码...

$('img.thumbnail').click(function() {
    clearInterval(slideShow);
    var src = $(this).attr("src");
    while ($('.container img:eq(1)').attr('src') != src) {
        $('#slideRight').trigger("click");
    }
});

当我点击缩略图时,什么也没有发生...我使用了警告语句来尝试调试,最终发生的是这样....
while循环执行,但第一次什么都不会发生。幻灯片根本没有被推进。从第二次开始执行,is('::animated')每次都会被触发,而slideRight事件的其余部分则不会被执行...
所以我的第一个问题是,有人能解释为什么第一次不运行吗?
我的第二个问题是,有没有办法在动画完成之前等待并继续循环?
任何帮助将不胜感激。谢谢!
2个回答

1
我将从你问题的第二部分开始,关于在继续循环之前完成动画。
我以前做过类似的事情,我的做法是设置两个全局变量来控制动画。一个变量用于指定周期的持续时间,另一个变量是自上次循环以来经过的时间计数器。
例如:
$timeToChange = 5; // in Seconds
$timeSinceReset = 0; // also in Seconds

将间隔设置为一秒钟,并调用一个新函数(autoAdvance()):

var slideShow = setInterval(function() {
    autoAdvance();
}, 1000); // only one second

然后使用计数器变量来计算每次间隔被调用的次数(每秒一次)。类似于:

function autoAdvance(){

    if($timeSinceReset == $timeToChange){

        $timeSinceReset = 0;

        $('#slideRight').trigger("click"); // execute click if satisfied
    }
    else{$timeSinceReset++;}

}

为了避免动画未完成时循环播放,请在单击缩略图时将$timeSinceReset重置为0(零)。可以尝试以下代码:
$('#thumbnail').click(function(){
    $timeSinceReset = 0;
});

这将为您提供一个不错的5秒缓冲时间(或者您设置的$timeToChange),然后循环继续。

至于您问题的第一部分,获取特定缩略图的编号,然后使用它来滚动到相应的图像。类似这样:

$('.thumb').click(function (each) {
    $childNumber = $(this).index();
});

你可以在 这个fiddle 中看到它。点击灰色框中的一个,它会告诉你你点击了哪一个。使用这个信息来滚动到相应的图像(如果你只有三个图像,则为1、2或3)。希望这能帮到你。

谢谢。两个变量的唯一问题是,如果您单击箭头,将不会发生任何事情。它有三种不同的访问照片的方式,点击左/右箭头(例如#slideRight按钮),幻灯片和缩略图。 - user3159369
该内容包含一个 .animate() 函数,实际上会在 300 毫秒内滑动图片。这就是阻止代码正常工作的动画。由于 div 宽度和边距的精确性质,动画必须完成才能再次运行该内容。 - user3159369
galsize() 是什么? - Birrel
函数galsize() { var diff = $('.gallery').width() - 2100; diff = (diff + 4) /2; 返回差异; } - user3159369
换句话说,它计算出边距应该是多少,以使第二张图片始终居中。 - user3159369
显示剩余3条评论

0

这里提供了一种可能的完整解决方案,可以在this fiddle中找到。

HTML:

顶部容器包含图像。在这个特定的例子中,我使用了三个div代替图像。无论您使用图像还是div,都不会改变任何内容。

<div class="holder_container">
    <div class="img_container">
        <div class="photo type1">ONE</div> 
        <div class="photo type2">TWO</div>
        <div class="photo type3">THREE</div>
    </div>
</div>

.img_container 包含所有的图片,它的宽度等于所有图片的宽度之和。在这种情况下,每个图片(.photo)的宽度为150像素,高度为50像素,因此 .img_container 的宽度为450像素,高度为50像素。.holder_container 的尺寸与单个图像相同。当运行时,.holder_container 被设置为隐藏任何溢出,而 .img_container 移动其位置左右。

还包括两个导航按钮(前进和后退)

<div class="nav_buttons">
    <div class="nav back"><<<</div>
    <div class="nav forward">>>></div>
</div>

还有三个缩略图 - 分别对应顶部容器中的每个图像

<div class="top">
    <div class="thumb"></div>
    <div class="thumb"></div>
    <div class="thumb"></div>
</div>

CSS:

请参考 JS Fiddle 获取所有 CSS 规则。

最重要的规则如下:

.holder_container {
    margin: 0px;
    padding: 0px;
    height: 50px;
    width: 150px;
    position: relative;
    overflow: hidden;
}
.img_container {
    margin: 0px;
    padding: 0px;
    height: 50px;
    width: 450px;
    position: relative;
    left: 0px;
    top: 0px;
}

在这个例子中,.type1.type2.type3仅用于给图像div着色,以便您可以看到动画效果。它们可以从您的代码中省略。 JavaScript: JavaScript包含以下元素...
变量:
var timeToChange = 3;   // period of the image change, in seconds
var timeSinceReset = 0; // how many seconds have passed since last image change
var currentImage = 1;   // Which image you are currently viewing
var totalImages = 3;    // How many images there are in total

功能:

autoAdvance - 每秒钟通过 setInterval 调用一次。计算自上次图像更改以来经过的秒数。如果经过的秒数等于周期,则调用一个函数来切换图像。

function autoAdvance() {
    if (timeSinceReset == timeToChange) {
        timeSinceReset = 0;
        moveNext();
    } else {
        timeSinceReset++;
    }
}

moveNext() - 移动到下一张图片。如果当前图片是最后一张(currentImage == totalImages),那么currentImages将被设置回1,并显示第一张图片。

function moveNext(){
    if(currentImage == totalImages){
        currentImage = 1;
        var newPos = 0 + 'px';      
        $('.img_container').animate({left: newPos}, 300);
    }else{
        currentImage++;
        var newPos = -((currentImage-1) * 150) + 'px'; // child numbers are zero-based  
        $('.img_container').animate({left: newPos}, 300);
    }
}

代码的其余部分:

如果其中一个缩略图被点击,则移动到相应的图像。

$('.thumb').click(function (each) {
    timeSinceReset = 0;
    var childNumber = $(this).index();
    currentImage = childNumber + 1; // child numbers are zero-based

    var newPos = -(childNumber * 150) + 'px'; // child numbers are zero-based   
    $('.img_container').animate({left: newPos}, 300);
});

如果点击导航按钮之一,则相应地移动。 如果单击“返回”,则向后移动一个图像(或者如果当前在第一个图像上,则移动到最后一个图像)。 如果单击“第一个”,则向前移动一个图像(或者如果当前在最后一个图像上,则移动到第一个图像)。
$('.nav').click(function(){
    timeSinceReset = 0;
    if($(this).hasClass('back')){ // Back button
        if(currentImage == 1){
            currentImage = totalImages;
        }else{
            currentImage--;
        }
    }else{ // Forward button
        if(currentImage == totalImages){
            currentImage = 1;
        }else{
            currentImage++;
        }
    }

    var newPos = -((currentImage-1) * 150) + 'px';      
    $('.img_container').animate({left: newPos}, 300);

});

这里是指向代码示例的链接


谢谢Birrel.....但是我决定只写新的代码来实现slideRight按钮的功能,只不过是用多个图片而不是多次触发点击事件。这似乎比尝试解决这个问题更容易。将所有图片从一开始就包含在DOM中的问题是,当它到达最后一个时,它不会循环回到开头,而是滑动到开头。感谢你的帮助。我非常感激你为此付出的努力。 - user3159369
你可以使用一种方法来优雅地从最后一个图像移动到第一个图像,反之亦然,即复制第一个图像并将其放置在最后一个图像之后,复制最后一个图像并将其放置在第一个图像之前。当您从最后一个图像移动到第一个图像时,向右滑动一个图像以显示第一个图像的副本,然后使用JS更改滑块的位置到第一个图像。请查看此网站 this 以了解我的意思。随意检查JavaScript以查看创建它的详细信息。希望一切顺利。 - Birrel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接