Pergunta

I have a with a set of images, all of which are the same height but different width. I need the to stay at a fixed width, and I need the images to slide to the left in an infinite loop. I also need the images to fill the container width, so that even partial images display. The scrolling will happen in steps (e.g. 200px) and at a set interval.

I have looked through a good number of jQuery slideshow plugins, including Cycle, NivoSlider, EasySlider, and half-a-dozen others. But none that I've seen seem to let me know exactly what a client needs wants it to do. I don't need clickable navigation, or centering. Just a continuous filmstrip that scrolls in set-width steps and a set interval.

I was thinking, as far as the continuous-loop part is concerned, is that I could wait until the left-most image has gone out of sight. Originally, I tried just using append(), but the slides jumped when the left-most was moved to the end. So then I tried to append() a clone() of it to the end $('#slides').children(), then remove() it from the beginning of $('#slides').

So far, I have:

<div id="outer" style="width:300px;">
    <div id="slides">
        <img src="/images/slide1.jpg" alt="" style="height:150px;width:200px;" />
        <img src="/images/slide2.jpg" alt="" style="height:200px;width:200px;" />
        <img src="/images/slide3.jpg" alt="" style="height:150px;width:200px;" />
        <img src="/images/slide4.jpg" alt="" style="height:300px;width:200px;" />
    </div>
</div>

and

/* some code ideas taken from easySlider */
(function($){
    $.fn.stepSlider = function() {
        var slideInterval;

        this.each(function() {
            // this will be the width of $('#slides')
            var width = 0;
            // shortcut I saw in easySlider code; liked it, used it.
            var o = $(this);
            // set width of $('#slides') based on total width of child images
            o.children().each(function(){width+=$(this).width();});

            function scroll() {
                o.children().each(
                    function(index){
                        // slide each of the children to the left by 150px
                        $(this).animate({'left':'-=150'}, 2000);
                    }
                );

                // after children have been animated() left, check to see
                // if the left-most child has gone out of sight
                if (o.children(':first-child').position().left + o.children(':first-child').width() < 0) {
                    // cloning the first child now
                    var el = o.children(':first-child').clone(true);
                    // removing the first child
                    o .children(':first-child').remove();
                    // trying to reset the css('left') of all of the children now that the first
                    // element is supposed to be gone
                    o.children().css('left', o.children(':first-child').position().left + o.children(':first-child').width());
                    // appending the clone()
                    o.append(el);
                }
            }

            slideInterval = setInterval(function(){scroll();}, 2000);
        });
    }
})(jQuery);

The sliding works. But the shifting of the first image to the end causes the slides to jump. And then the thing just starts breaking down to the point of stopping altogether.

Any insight is greatly appreciated. No, I'm not completely new to jQuery, but yes: this is my first plugin attempt.

Thanks and best regards

Foi útil?

Solução

I'd suggest you can use the scrollTo plugin (or write your own). The following will scroll an area by 300 px so it doesn't matter what you put in it. You'll have to manage the position and the width of the area to stop at the end or do as you need.

ScrolTo: http://demos.flesler.com/jquery/scrollTo/

JSFiddle: http://jsfiddle.net/YZ9vA/2/

    $(document).ready(function(){
    var areaWidth = 0, x=0;        
    $('#slideshow img').each(function() {
        areaWidth = areaWidth + $(this).width();
    });
    $('#slideshow').width(areaWidth);

    function ScrollMe() {
     x += 300;
     $('#sliders').scrollTo({top:0, left:x},800);

     }


   setInterval(ScrollMe,1000);

});​

Original Answer:

My suggestion to you is to use jquery cycle which will repeat forever. Instead of cycling images, cycle divs that way you can set those widths to 200px and the images inside you can place however you need (centered, width 100%, etc).

http://jquery.malsup.com/cycle/

#slides, #slides div {width:200px;height:300px}
#slides img {width:100%;height:100%}  

<div id="slides">
    <div><img src="/images/slide1.jpg" alt="" style="" /></div>
    <div><img src="/images/slide2.jpg" alt="" style="" /></div>
    <div><img src="/images/slide3.jpg" alt="" style="" /></div>
    <div><img src="/images/slide4.jpg" alt="" style="height:300px;width:200px;" /></div>
<!-- I left the last inline style on, you can use that to override or use css externally -->
</div>

$('#slides').cycle({fx:'scrollHorz', 
                   continuous: 1, 
                   easeIn: 'linear',
                   easeOut: 'linear'});

Outras dicas

So thanks to all of lucuma's help , I have something working.

CSS:

<style type="text/css">
    #outer  {height: 250px; width: 760px; overflow:hidden;}
    #mid    {height: 250px; width: 760px; overflow:hidden;}
    #slides {height: 250px; width: auto; overflow:hidden;}
    #slides img {float: left; height: 250px;} /* height specified just for clarity */
</style>

HTML:

I had to wrap the #slides div in two other divs instead of one. With just one wrapper, the scrollTo plugin ended up setting the divs to 100% width rather than honoring my 760px constraint. Due to time constraints, I didn't investigate this further. I just added the extra div and called it a day.

<div id="outer">
    <div id="mid">
        <div id="slides">
            <img src="images/image1.jpg" alt="" style="width:760px;" />
            <img src="images/image2.jpg" alt="" style="width:529px;" />
            <img src="images/image3.jpg" alt="" style="width:720px;" />
            <img src="images/iamge4.jpg" alt="" style="width:563px;" />
            <!-- my live version has 16 total images -->
        </div>
    </div>
</div>

JavaScript:

<script type="text/javascript" src="scripts/jquery.scrollTo.min.js"></script>
<script type="text/javascript">
    $(function(){
        var areaWidth = 0, x = 0, lelements=$('#slides img').length * -1;

        /* This is the same essential functionality that I had in my original post
         * to set the width of the images container
         */
        function setWidth() {
            $('#slides img').each(function() {
                areaWidth = areaWidth + $(this).width();
            });
            $('#slides').width(areaWidth);
        }

        /* This is also essentially what I was doing before: checking
         * to see if an image is no longer viewable. It appends a clone
         * to the $('#slides'), but it differs from my original idea by
         * not trying to remove any :first element.
         * So $('#slides img').length will continue to increase as the
         * program runs. I was trying to avoid this, but in reality, it
         * probably doesn't matter a ton unless someone is watching the
         * same page for quite a long time.
         */
        function checkIt() {
            $('#slides img').slice(lelements).each(function() {
                if ($(this).position().left + $(this).width() < 0) {
                    $(this).clone().appendTo($('#slides'));
                }
            });
        }            

        /* This is where we use Flesler's scrollTo plugin to handle the motion.
         * I changed scrollTo({}, 3000) to scrollTo({}, {duration: 1000})
         * to slow the transition speed.
         */
        function scrollMe() {
            $('#outer').scrollTo({top:0, left:x}, {duration:1000});

            /* x += 300 was the first line in scrollMe(), but ended up
             * resulting in a 600px slide for the first transition,
             * so I moved it here. The first transition takes longer
             * to occur, but all other transitions are fine
             */
            x += 300;

            checkIt();
            setWidth();
        }

        setInterval(scrollMe, 3000);  
    });
</script>

One other thing I had to do was make sure my first slide was the full width (760px). If it was less than that, then the second image would initially be invisible, then it would suddenly appear in the left space of the container, and then the scrolling would happen. All subsequent images were fine. Obviously, having the first image fill the full width eliminates that artifact.

Thanks again to lucuma - you were a TON of help!

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top