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
currentclass 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'
});