jQuery 添加按钮时幻灯片中断

jQuery Slideshow Breaks when I add buttons

我一直在尝试创建可以使用单选按钮(或几乎任何类型的按钮)进行更改的幻灯片。我已经让幻灯片放映本身开始工作,可以看到 here,但是,当我尝试向等式添加按钮时,整个事情都崩溃了。现在它向我展示的只是最后一张图片,然后它逐渐消失到倒数第二张图片。这是我目前正在使用的功能。

    $(function () {
    "use strict";
    setInterval(function(){rotateImages()}, 4000);

    var pic1 = $('#slideshow div:first');
    var pic2 = $('#slideshow div:nth-child(2)');
    var pic3 = $('#slideshow div:nth-child(3)');
    var pic4 = $('#slideshow div:nth-child(4)');
    var pic5 = $('#slideshow div:last');

    $("#choosePic1").click(rotateImages(pic1));
    $("#choosePic2").click(rotateImages(pic2));
    $("#choosePic3").click(rotateImages(pic3));
    $("#choosePic4").click(rotateImages(pic4));
    $("#choosePic5").click(rotateImages(pic5)); 

});

function rotateImages(manualChange) {


    var CurrentPhoto = $('#slideshow .current');
   if (manualChange !== null) {
        CurrentPhoto = manualChange;   
    }
    var NextPhoto = CurrentPhoto.next();
    if (NextPhoto.length === 0) {
        NextPhoto = $('#slideshow div:first');
    }
    CurrentPhoto.removeClass('current').addClass('previous');
    NextPhoto.css({
        opacity: 0.0
    }).addClass('current')
        .animate({
        opacity: 1.0
    }, 1000,

    function () {
        CurrentPhoto.removeClass('previous');
    });
}

我把CSS和HTML的伴奏留在了JSFiddle上,可以看到here

为什么当我添加按钮时整个功能会中断?

  1. 因为你的 $("#choosePic1").click(rotateImages(pic1)); 会立即用 pic1 调用旋转图像,你必须使用 .bind 为 [=16] 创建一个新函数=] 使用给定参数调用的事件。

  2. if (manualChange !== null) 仅当 manualChange 更改为 null 时才为真,如果您不给 manualChange 赋值并离开 undefined, if 测试将变为 false,然后 CurrentPhoto 将分配 undefined.

  3. 按照您的逻辑,您应该在 CurrentPhoto = manualChange; 中分配的内容应该是 NextPhoto = manualChange;,因为您的意图似乎改变了用户 selected 图片。

  4. 加一个.stop(true, true)让动画直接跳到最后应该播放的地方

  5. :nth-child(2) 将匹配 #sildeshow 中的第 2 个 children 但是,在你的 #slideshow 中,第一个元素是 <span>,因此 $('#slideshow div:first') 将 select 与 $('#slideshow div:nth-of-type(2)') 相同的项目,其他项目也是如此。你应该使用 :nth-of-type(2) 到 select 第二个 div in #slideshow,所以对其他人。

  6. 可以进一步使用setTimeout代替setInterval,这样更容易取消下一次自动旋转,防止与手动播放的动画重叠,rotateImages末尾的setTimeout使它会重新启动自动播放。

$(function () {
    "use strict";
    setInterval(function () {
        rotateImages()
    }, 4000);

    var pic1 = $('#slideshow div:first');
    var pic2 = $('#slideshow div:nth-of-type(2)');
    var pic3 = $('#slideshow div:nth-of-type(3)');
    var pic4 = $('#slideshow div:nth-of-type(4)');
    var pic5 = $('#slideshow div:last');
    
    // use .bind to create new function which when executed, will execute rotateImages and pass picX as its param.
    $("#choosePic1").click(rotateImages.bind(null, pic1));
    $("#choosePic2").click(rotateImages.bind(null, pic2));
    $("#choosePic3").click(rotateImages.bind(null, pic3));
    $("#choosePic4").click(rotateImages.bind(null, pic4));
    $("#choosePic5").click(rotateImages.bind(null, pic5));

});

function rotateImages(manualChange) {
 

    var CurrentPhoto = $('#slideshow .current');
    var NextPhoto;
    // Use != null to test undefined and null
    if (manualChange != null) {
        // Assign it to NextPhoto
        NextPhoto = manualChange;
    } else {
        NextPhoto = CurrentPhoto.next();
    }
    if (NextPhoto.length === 0) {
        NextPhoto = $('#slideshow div:first');
    }
    CurrentPhoto.removeClass('current').addClass('previous');
    // Use .stop to skip current playing (if caused by autoRotate) and start the newest.
    NextPhoto.stop(true, true).css({
        opacity: 0.0
    }).addClass('current')
        .animate({
        opacity: 1.0
    }, 1000,

    function () {
        CurrentPhoto.removeClass('previous');
    });
}
#slideshow div {
    z-index: 0;
    position: absolute;
}
#slideshow div.previous {
    z-index: 1;
}
#slideshow div.current {
    z-index: 2;
}
.slideshowSelect {
   height:22px;
    width: 22px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id="slideshow"> <span class="buttons">
                 <input type="button" id="choosePic1" class="slideshowSelect" value="1">
                <input type="button" id="choosePic2" class="slideshowSelect" value="2">
                <input type="button" id="choosePic3" class="slideshowSelect"value="3" >
                <input type="button" id="choosePic4" class="slideshowSelect" value="4">
                <input type="button" id="choosePic5" class="slideshowSelect" value="5">
                </span> 
    <div class="current">
        <img src="http://lorempixel.com/400/200/abstract/" alt="Img" height="382" width="594">
    </div>
    <div>
        <img src="http://lorempixel.com/400/200/people/" alt="Img" height="382" width="594">
    </div>
    <div>
        <img src="http://lorempixel.com/400/200/sports/" alt="Img" height="382" width="594">
    </div>
    <div>
        <img src="http://lorempixel.com/400/200/animals/" alt="Img" height="382" width="594">
    </div>
    <div>
        <img src="http://lorempixel.com/400/200/nature/" alt="Img" height="382" width="594">
    </div>
</div>

我认为你的想法是根据点击显示相应的图像。您所做的是,将手动选择设置为当前图像,而您应该将其设置为下一张图像,因为根据您的 逻辑 将要显示的图像。

您也可以将 setInterval 替换为 setTimeout,以确保动画始终在下一个队列开始之前完成。

要检查参数是否传递给函数,您可以简单地执行 if (param) 而不是 if (param !== null)

您还必须通过 .length 检查元素是否存在,即使在您的情况下没有必要,因为您在图像和按钮之间有适当的映射。

最重要的位是:

用户体验:每当您需要根据设置的间隔中断自动播放的动画时,清除间隔。如果你不这样做,那将是一种糟糕的体验,因为自动播放会继续进行,即使你不想要它,因为手动干预的全部目的就是看到那个特定的图像!

代码优化:Jquery/JavaScript 提供了通过各种内置方法最小化代码的方法。利用它们可以减少您编写的代码行,并使其在将来更易于管理。我已经完成了 click 位作为演示。我相信在这个片段中还有更多内容。

看看下面修改后的代码。

$(function () {
    "use strict";
    var timer = setInterval(rotateImages, 2000);
    
    $(".buttons").on("click", ".slideshowSelect", function() {
        
        clearInterval(timer);
        var photoIndex = parseInt($(this).val(), 10) - 1;
        rotateImages( $('#slideshow div').eq(photoIndex) );
        
        //Give an option to the user thru a button to resume auto play
        //or resume auto play after a set amount of time
        setTimeout(function() {
            timer = setInterval(rotateImages, 2000);
        }, 5000);
    });
    
    function rotateImages(manualChange) {

        var CurrentPhoto = $('#slideshow .current');
        var NextPhoto = CurrentPhoto.next();
        
        if (manualChange && manualChange.length) {
            NextPhoto = manualChange;
        }
        if (NextPhoto.length === 0) {
            NextPhoto = $('#slideshow div:first');
        }
        CurrentPhoto.removeClass('current').addClass('previous');
        NextPhoto.css({
            opacity: 0.0
        }).addClass('current')
        .animate({
            opacity: 1.0
        }, 1000, function () {
            CurrentPhoto.removeClass('previous');
        });
    }
});
#slideshow div {
    z-index: 0;
    position: absolute;
}
#slideshow div.previous {
    z-index: 1;
}
#slideshow div.current {
    z-index: 2;
}
.slideshowSelect {
   height:22px;
    width: 22px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="slideshow">

    <span class="buttons">
        <input type="button" class="slideshowSelect" value="1" />
        <input type="button" class="slideshowSelect" value="2" />
        <input type="button" class="slideshowSelect"value="3" />
        <input type="button" class="slideshowSelect" value="4" />
        <input type="button" class="slideshowSelect" value="5" />
    </span>

    <div class="current">
        <img src="http://www.butterfly-tattoo-design.com/butterfly-tattoos-6926.jpg" alt="Img" width="300" />
    </div>
    <div>
        <img src="http://www.serendipitystamps.com/mm5/pics/stamps/1255FloralButterflyStamp.gif" alt="Img" width="300" />
    </div>
    <div>
        <img src="http://images.clipartpanda.com/free-butterfly-clipart-RcGjaR7cL.jpeg" alt="Img" width="300" />
    </div>
    <div>
        <img src="http://www.cgvector.com/wp-content/uploads/2011/04/Vector_Butterfly_000018.jpg" alt="Img" width="300" />
    </div>
    <div>
        <img src="http://www.weddingchaos.co.uk/images-content/animals/butterfly.jpg" alt="Img" width="300" />
    </div>
</div>