Fork me on Github

Slider.js v1.1: Slideshow with jQuery, CSS Transitions and Canvas

Slider.js is an easy-to-use customizable Javascript library to create image slideshows.

We are working hard on the next version of Slider.js with new ideas:

more customization, a live editing system to contribute to new themes and transitions with Github (gist), a build system for making custom packages, a brand new transition mode using WebGL shaders, and much more...

Overview

Demo

Slider.js relies on latest web technologies: the power of CSS Transitions to perform awesome and efficient effects and the HTML5 Canvas to perform some non trivial transitions.

Slider options

Why using Slider.js?

Basic features

  • Each slide displays the image, but can also have a text caption and a link.
  • Slides navigation (pages, next, previous)
  • Load images before starting the slider.
  • Load the slider photos with a JSON object (distant or local).

Highly extensible and customizable

Transitions

Choose your transition among 13 available CSS Transitions and 10 built-in Canvas transition functions.

Implement your own transition in the technology you mastery:

  • Style your own CSS transitions which fit the best your needs.
  • Implement your own render function manipulating images pixels and Canvas API.

Themes

Choose or style your own theme.

Features

Extend the API with new features. (see our Flickr example)

Lightweight

slider.min.js
11K
slider.min.css
8.2K

Efficient

Unlike many Javascript and jQuery image sliders, Slider.js animation implementation is simple, clean and do not parse/manipulate DOM style attributes with Javascript each render frame rate.
Slider.js is an hybrid solution taking the efficiency of CSS3 transitions and the power of Canvas animation based on requestAnimationFrame.

More details in the technical part.

Browser compatibility

This library intends to work perfectly with latest browsers (Chrome, Firefox 4+, Safari, IE10).

On older browsers (like IE6, FF3.0, ...) CSS Transitions aren't supported, it means that there are no animations but the slider works, it's not broken, because CSS by its nature provides a graceful degradation.
Open question: Do old browser users care about animations?

A Canvas usage falls back on CSS version if Canvas is not supported.

Usage and API

Best way is to hack...

...the source code:

Try it live with your web console:

Open your web console and play with the slider variable.

Slider.js

The Slider constructor takes an empty container DOM node in argument. var slider = new Slider($('#sliderContainer'));

You can start the slider by setting photos through a JSON object: slider.setPhotos([ { "src" : "images/evil-frank.png", "name": "Big Buck Bunny" }, { "src" : "images/s1_proog.jpg", "name": "Elephant Dreams" } ]); The format of this JSON is an Array of { src, name (optional), link (optional) }

Or fetch this JSON with AJAX: slider.fetchJson('photos.json');

Don't forget to set your slider images size: slider.setSize(400, 300);

Themes and CSS transitions can be switched live with these methods: slider.setTheme('theme-dark'); slider.setTransition('transition-zoomin');

For the Canvas usage, see the canvas part section.

Advanced usages

Stop the slider if needed: slider.stop();

And (re)start it: slider.start();

To manually change slides, use: slider.next(); // next slide slider.prev(); // previous slide slider.slide(4); // go to slide number 4

You can chain different methods in any order slider.setSize(400, 300) .fetchJson('photos.json') .slide(5) .setTheme('theme-light') .setTransition('transition-zoomout');

The CSS

To implement your own slider CSS transitions, choose a transition name and describe what change between (at least) 2 selectors.

For instance using tn transition name you could define rules for .slider.tn .slider-image and .slider.tn .slider-image.current.

Example: Zoom in transition

/* zoom in */ .slider.transition-zoomin .slide-image { transform: scale(2); } .slider.transition-zoomin .slide-image.current { transform: scale(1); }

Example: Left transition

/* left transition */ .slider.transition-left .slide-image { opacity: 1; left: -100%; } .slider.transition-left .slide-image.current { left: 0; } .slider.transition-left .slide-image.current ~ .slide-image { left: 100%; }

Note that using a Canvas transition, the CSS transition is still used for the caption text.

On the same principle, you can define your own slider themes with CSS:

Example: dark theme

Less source code: .slider.theme-dark { background: black; color: white; a { color: white; } .caption { background: rgba(0,0,0,0.5); } .options a { color: #91BECC; &:hover { color: #D3E5EB; } } .slide-image { background: black; } .slide-pager a.current { background-color: #91BECC; color: black; } .loader .spinner { background: url(load_dark.gif) no-repeat; } }

Canvas API

Using the Canvas API is optional. Most of times, CSS transitions can fit your needs. But if you want more effects manipulating images, you need to handle your own render function.

setTransitionFunction

You can use setTransitionFunction to set the transition function.

  • Pick one of the built-in transition functions: slider.setTransitionFunction(SliderTransitionFunctions.clock);
  • Or implement your own transition function.
    Basically, you implement the render method, the loop function called during the transition: slider.setTransitionFunction({ render: function(slider, from, to, progress){ // draw the current transition from image from to to with progress percent. } });

This render function must be efficient because it directly impacts the render frame rate.

If you use datas which never change between two render frames, you could preload these datas implementing the init method.

For instance, you could extract once the Canvas ImageData from the two transition images: slider.setTransitionFunction({ init: function(self, from, to) { return SliderUtils.extractImageData(self, from, to); }, render: function(slider, from, to, progress, externalDatas){ // externalDatas.fromData // externalDatas.toData // externalDatas.output ... } });

There are some util functions (we just see a extractImageData usage before).
You should also use the clippedTransition util function for most of your Canvas transitions.

Example with the circle transition: slider.setTransitionFunction({ render: SliderUtils.clippedTransition(function(ctx, w, h, p) { return ctx.arc(w / 2, h / 2, 0.6 * p * Math.max(w, h), 0, Math.PI * 2, false); }) })

setTransitionDuration

You can also define the transition duration.

Using CSS transitions, this transition duration can be overriden with the transition-duration property. But with Canvas, you must use the setTransitionDuration method. It takes the duration in milliseconds. slider.setTransitionDuration(1500) // the default

How does it work?

Let's go deeper and see how things are working under the hood.

Canvas Animations VS CSS Transitions

Slider.js provides a transparent Canvas or CSS transitions support: Whatever the technology you choose for the transition, the slider should work properly and in a same way.

But each technology has its own good and bad points:

Canvas CSS Transitions
Usability Medium (Javascript and Canvas API knowledge required) Easy
Performance Good (thanks to requestAnimationFrame) Very good
Possibilities Infinite (you manipulate pixels how you want) Limited (to CSS)

How CSS transitions work

CSS Transitions allows property changes in CSS values to occur smoothly over a specified duration. (spec)

CSS Transitions are a way to easily add animations to a web page. Basically, it allows us to perform an animation between two given states by adding one CSS property: transition (derived in 4 sub-properties). CSS properties will change CSS values, which will be animated smoothly over a specified duration.

To use CSS Transitions, like in a state machine, we firstly need to identify states and actions. States are CSS selectors and actions are changes made between these CSS selectors.

It's that simple!

It let the browser rendering animation instead of using javascript complex code. You don’t have to worry about animation and performance. So you can stay focused on what changes and describe it in CSS.

In our slider, CSS and Javascript are split and independent:

  • The javascript part just does ajax stuff, templating and change a few classes. To perform slide change, only a current class is moved.
  • The CSS part styles the slider and use classes set by Javascript to perform Slider effects with CSS Transitions.

For instance, slider.setTransition('transition-left') will set a transition-left class which will be used in CSS to describe the transition with CSS3 Transitions.

Hence, you can add your own transitions very easily. Mixing with CSS3 Transforms, effects are incredible and very efficient (animations are rendered by your browser : accelerated and optimized).

How Canvas animation works

Mmh, Canvas?

A Canvas element is used for some more advanced transitions which are impossible to implement using CSS Transitions.

A Canvas is basically a pixels area in which you have a full access of each pixel. Hopefully, Canvas also provides some APIs like the Canvas 2D Context API.

requestAnimationFrame is exactly designed for animation looping

To perform the transition animation, we need to loop during the animation (and only at that time) to render the progressing state change. Looping means iterate as fast as possible to render a frame on the Canvas.

In our slider, each slide change is performed by calling the slide method which takes in argument the number of the slide to switch to.

The slide method will init the render animation for a specific transition function (transitionFunction) and during a specific duration (duration) by calling startRender.

This method will init "constant" variables for the current transition by calling the transitionFunction.init function if defined. For a same transition, the "from" image and the "to" image are constant, so we have sometimes some constant variables which could be init once (like the CanvasDataImage objects of both images).

Once done, we init the render animation loop by calling the render method.

In this method, we determine the progress of the transition (from 0% to 100%). If the transition is finished, we draw the final image until the next transition comes. But if the transition is in progress, we call the transitionFunction.render method by passing all variables this method can deal with (including the canvas context, the constant variables, ...) and we recall the render method to immediately redraw the next animation frame.

But to handle this recall, we really need to use the requestAnimationFrame which is exactly designed for animation looping. Older Javascript codes was using setTimeout or setInterval which is bad. (Some libraries like jQuery are today still using it for animating).

Using this method, the browser knows explicitly what you are doing and can optimize the animation for you. It takes two arguments: the function to call for the next frame (here it's render) and the node element in which the animation occurs.

This second argument is essential for the optimization. For instance, if the Canvas is not visible in the viewport (means that you scroll down and not see it anymore), the browser can stop (or slow down) the requestAnimationFrame frame rate. It wasn't the case with setTimeout / setInterval usages.

I think there are much more optimizations made by the browser using this method (optimizations I don't know because I haven't hack some low level render engine codes yet).

Implementation notes

We tried to keep independence between the slider engine, the CSS Transitions support and the Canvas support.

To perform that, a first class implements the slider engine and target CSS Transitions. A second class extends it and provides the Canvas transition feature. It's the Slider class.

CoffeeScript makes the inherence easier for Javascript.

Hack-ability - Flickr example

With this Slider API. Let's see how to easily retrieve flickr photos.

Implementation

Let's create a new slider var slider = new Slider($('#sliderContainer')); Now, let's create a new method in this slider : slider.fetchFlickr = function(options) { this.fetchJson('http://www.flickr.com/services/rest/?jsoncallback=?', $.extend({ method: 'flickr.photos.getRecent', per_page: 10, format: 'json', api_key: 'be902d7f912ea43230412619cb9abd52' // Your API key }, options), function(json){ return $.map(json.photos.photo, function(photo){ return { link: 'http://www.flickr.com/photos/'+photo.owner+'/'+photo.id, src: 'http://farm'+photo.farm+'.static.flickr.com/'+ photo.server+'/'+photo.id+'_'+photo.secret+'_z.jpg', name: photo.title.substring(0,20) } }); }); return this; }

In only 18 lines of code, we have created an awesome flickr slider!

Let's see deeply this code source here: fetchFlickr.js annoted source.

You could also implement it in a more OO way with inherence (easy with CoffeeScript).

Usage

Default behavior: get recent Flickr photos. slider.fetchFlickr();

You can override default flickr options by passing params (see flickr API).

Retrieve 30 recent photos searching "China": slider.fetchFlickr({ per_page: 30, method: 'flickr.photos.search', text: 'China' });

Comments