Thursday, 29 January 2015

jQuery image slider

This tutorial is for beginners. The method for creating the slider could be done differently, but I feel this way is more simple to understand.

It is important to picture what the HTML and CSS should be doing in order to create the component before actually beginning with the javascript. This way you know exactly what you are working towards. Below is a gif explaining the concept of the slider in terms of HTML and CSS.
slider-gif
Common things that cross my mind before actually jumping into development are:
Where are the hidden elements situated?
Beneath, on top, next to or behind the visible element?
How are they hidden?
Is their display set to none?
Are they outside of the parent element which is set to overflow: hidden?
Are they hidden behind visible element via z-index?
All right, enough of that, let’s get started.

The HTML

Before we create anything, we should try and get an idea of exactly what we are trying to achieve. I’ve drawn up a quick image slider wireframe.
So let’s turn that into HTML.
<div class="gallery-wrap">
  <div class="gallery clearfix">
    <div class="gallery__item">
      <img src="images/image1.jpg" class="gallery__img" alt="" />
    </div>
     <div class="gallery__item">
      <img src="images/image2.jpg" class="gallery__img" alt="" />
    </div>
  </div>
  <div class="gallery__controls clearfix">
    <div href="#" class="gallery__controls-prev">
      <img src="images/prev.png" alt="" />
    </div>
    <div href="#" class="gallery__controls-next">
      <img src="images/next.png" alt="" />
    </div>
  </div>
</div>
.gallery-wrap will be the visible area.
.gallery is the element that contains the list of images.
.gallery__controls contains the next and previous controls.
Generally an image slider would contain more than 2 images but I’ve left out the exact HTML I used in the demo for readability.

The CSS

.gallery-wrap { margin: 0 auto; overflow: hidden; width: 732px; }
.gallery { position: relative; left: 0; top: 0; }
.gallery__item { float: left; list-style: none; margin-right: 20px; }
.gallery__img { display: block; border: 4px solid #40331b; height: 175px; width: 160px; }

.gallery__controls { margin-top: 10px; }
.gallery__controls-prev { cursor: pointer; float: left; }
.gallery__controls-next { cursor: pointer; float: right; }
The most important thing here is to set .gallery to ‘position: relative‘ and to set.gallery-wrap to ‘overflow: hidden‘. The CSS is quite straight forward.

The jQuery/Javascript

This is where all the fancy tricks take place.
// Only run everything once the page has completely loaded
$(window).load(function(){

    // Fancybox specific
    $(".gallery__link").fancybox({
        'titleShow'     : false,
        'transitionIn'  : 'elastic',
        'transitionOut' : 'elastic'
    });

    // Set general variables
    // ====================================================================
    var totalWidth = 0;

    // Total width is calculated by looping through each gallery item and
    // adding up each width and storing that in `totalWidth`
    $(".gallery__item").each(function(){
        totalWidth = totalWidth + $(this).outerWidth(true);
    });

    // The maxScrollPosition is the furthest point the items should
    // ever scroll to. We always want the viewport to be full of images.
    var maxScrollPosition = totalWidth - $(".gallery-wrap").outerWidth();

    // This is the core function that animates to the target item
    // ====================================================================
    function toGalleryItem($targetItem){
        // Make sure the target item exists, otherwise do nothing
        if($targetItem.length){

            // The new position is just to the left of the targetItem
            var newPosition = $targetItem.position().left;

            // If the new position isn't greater than the maximum width
            if(newPosition <= maxScrollPosition){

                // Add active class to the target item
                $targetItem.addClass("gallery__item--active");

                // Remove the Active class from all other items
                $targetItem.siblings().removeClass("gallery__item--active");

                // Animate .gallery element to the correct left position.
                $(".gallery").animate({
                    left : - newPosition
                });
            } else {
                // Animate .gallery element to the correct left position.
                $(".gallery").animate({
                    left : - maxScrollPosition
                });
            };
        };
    };

    // Basic HTML manipulation
    // ====================================================================
    // Set the gallery width to the totalWidth. This allows all items to
    // be on one line.
    $(".gallery").width(totalWidth);

    // Add active class to the first gallery item
    $(".gallery__item:first").addClass("gallery__item--active");

    // When the prev button is clicked
    // ====================================================================
    $(".gallery__controls-prev").click(function(){
        // Set target item to the item before the active item
        var $targetItem = $(".gallery__item--active").prev();
        toGalleryItem($targetItem);
    });

    // When the next button is clicked
    // ====================================================================
    $(".gallery__controls-next").click(function(){
        // Set target item to the item after the active item
        var $targetItem = $(".gallery__item--active").next();
        toGalleryItem($targetItem);
    });
});
I have heavily commented the above code. All lines beginning with // are comment lines.
To recap, the following was done:
  • Only run everything once the window (page) loads.
  • Calculate the total width of all the images.
  • Calculate the maximum scroll position. This is the total images width subtract the viewport (.gallery) width.
  • Create the toGalleryItem function. This function will scroll to any item we desire.
    • If the target item exists, continue. Otherwise there is nothing left to run.
    • The new position is the left position of the slide/image, relative to it’s container .gallery.
    • If the new position is less than or equal to the maximum scroll position, toggle active classes accordingly and animate to the new left position.
    • Otherwise animate to the maximum scroll position.
  • Set slide container (.gallery) width to the sum of all the images width.
  • Set the first image as active.
  • When the previous button is clicked, go to the previous slide/image.
  • When the next button is clicked, go to the next slide/image.
I will break down the javascript into 2 parts.
I’m going to break the above up into 2 parts. Part explaining the variable declarations and part 2 explaining the rest of the jQuery/javascript.

Summary of javascript/jQuery methods used:

$(".gallery__item").each()

I’ve written an article explaining the various jQuery each methodsa>.

totalWidth = totalWidth + $(this).outerWidth(true);

function toGalleryItem($targetItem)

A function is a bit of javascript that can be run just by calling the function name. Essentially it’s a shortcut. Functions can be made dynamic by allowing the user to pass in variables or parameters such as $targetItem

if($targetItem.length){

I’ve written an article about the if statement you may want to have a look at.

addClass and removeClass

These are self explanetory jQuery functions.

$(".gallery").animate()

This is a magic jQuery function that allows you to animate a wide range of CSS properties.

0 comments:

Post a Comment