jQuery: Every 5 seconds, automatically click on ne

2020-02-14 07:12发布

I have a given list of images, presented as thumbnails:

<ul id="thumbs">
    <li class="small-img"><img src="images/feature1.png" /></li>
    <li class="small-img"><img src="images/feature2.png" /></li>
    <li class="small-img"><img src="images/feature3.png" /></li>
</ul>

I use jQuery so that, when the user clicks on an image, it replaces the featured image in a div (which I got from another StackOverflow Ask):

$('#thumbs img').click(function(){
    $('div.feature-photo img').hide().attr('src',$(this).attr('src')).fadeIn();
});

My question is: Is there a way to make it into a slideshow? Maybe automatically "click" on the next picture every 5 seconds? Does setInterval play a part in this? I'm trying to be really basic about it, and avoid using more plugins than I have to. (But if there is no other way, I will consider it..)

Would appreciate any kind of help.

5条回答
【Aperson】
2楼-- · 2020-02-14 07:37

You need to think in terms of what your code should do, not what the user does that triggers your code. So rather than "automatically 'click'", you just want your code to automatically show the next image.

So the first step is to move your code out of the click handler:

function showImage(img){
    $('div.feature-photo img').hide().attr('src',$(img).attr('src')).fadeIn();
}

$('#thumbs img').click(function() {
    showImage(this);
});

And then the question becomes: How do I call showImage every five seconds with the "next" image. Well, first we'll want to remember what the "current" image is. Easy enough to modify our showImage to do that:

var current = null;
function showImage(img){
    current = img;
    $('div.feature-photo img').hide().attr('src',$(img).attr('src')).fadeIn();
}

So then we just need a trigger to occur in five seconds. You can use setInterval, but I find it's really easy to have it get out of control, so I use a chained series of setTimeout instead, where each one sets up the next. And what would be a good trigger for that? Well, five seconds after the user clicks an image, so probably right there in showImage:

var current = null;
var timer = 0;
function showImage(img){
    current = img;
    $('div.feature-photo img').hide().attr('src',$(img).attr('src')).fadeIn();
    if (timer) {
        clearTimeout(timer);
    }
    timer = setTimeout(nextImage, 5000);
}

Okay, so what should nextImage look like? I'd say we probably want to use current, perhaps:

function nextImage() {
    var $current;

    if (timer) {
        clearTimeout(timer);
        timer = 0;
    }
    if (current) {
       $current = $(current);
       next = $current.nextAll("img")[0];
       if (!next) {
           $current.siblings("img")[0];
       }
       if (next) {
           showImage(next);
       }
    }
}

You might kick things off at the beginning by showing the first image:

showImage($("#thumbs img")[0]);

So bringing that all together, and making sure we wrap it in a scoping function so we don't create global symbols:

(function() {
    var current = null;
    var timer = 0;

    function showImage(img){
        current = img;
        $('div.feature-photo img').hide().attr('src',$(img).attr('src')).fadeIn();
        if (timer) {
            clearTimeout(timer);
        }
        timer = setTimeout(nextImage, 5000);
    }

    function nextImage() {
        var $current;

        if (timer) {
            clearTimeout(timer);
            timer = 0;
        }
        if (current) {
           $current = $(current);
           next = $current.nextAll("img")[0];
           if (!next) {
               $current.siblings("img")[0];
           }
           if (next) {
               showImage(next);
           }
        }
    }

    $('#thumbs img').click(function() {
        showImage(this);
    });
    showImage($("#thumbs img")[0]);

})();

(Or instead of a vanilla scoping function, you might use jQuery ready.)

The above is fairly rough, and completely untested, but you get the idea.

查看更多
家丑人穷心不美
3楼-- · 2020-02-14 07:40

setInterval might be the answer to your question

var currImg = 0;
var $images;
$(document).ready(function() {
    $images = $('#thumbs img');
    changeImg();
    window.setInterval(function() {
        currImg++;
        if(currImg == $images.length) currImg = 0;
        changeImg();
    }, 5000);
});

function changeImg() {
    $('div.feature-photo img').hide().attr('src',$images.eq(currImg).attr('src')).fadeIn();
}
查看更多
不美不萌又怎样
4楼-- · 2020-02-14 07:52

You can go with the plain JQuery way, if you like. Here's my try

var intervalId;
$(function(){


function cycleImage(){

    var onLastLi = $("#thumbs li:last").hasClass("current");       
    var currentImage = $("#thumbs li.current img");
    var targetImage = $('div.feature-photo img');             
    $(targetImage).hide().attr('src', $(currentImage).attr('src')).fadeIn();

    var currentLi = $("#thumbs li.current");
    currentLi.removeClass("current");

    if(onLastLi){
        $("#thumbs li:first").addClass("current");
    }else{        
        currentLi.next().addClass("current");
    }

};

 intervalID = setInterval(cycleImage, 5000);



})

And you can find it in action here

查看更多
Deceive 欺骗
5楼-- · 2020-02-14 07:52

You could use

setTimeout(function(){
    //trigger next picture}
,5000);

But you have to keeep in mind that if the user reloads the page, the Timeout starts from zero !

查看更多
孤傲高冷的网名
6楼-- · 2020-02-14 07:55

You may easily calculate the next image within the switch function. This way you won't mess up your var space ;)

(function switchToImage(img) {
  $(img).click()
  var images = $('#thumbs img');
  var nextIndex = ($.inArray(images, img) + 1) % images.length;
  setTimeout(function() { 
    switchToImage(images[nextIndex]) 
  }, 5000);
})($('#thumbs img')[0]);
查看更多
登录 后发表回答