PHP Classes

File: kb/kenburns.js

Recommend this page to a friend!
  Classes of Barton Phillips   Slide Show   kb/kenburns.js   Download  
File: kb/kenburns.js
Role: Auxiliary data
Content type: text/plain
Description: Auxiliary data
Class: Slide Show
Present a slide show of local or remote images
Author: By
Last change: Update of kb/kenburns.js
Date: 7 days ago
Size: 15,714 bytes
 

Contents

Class file image Download
/* * Jquery Kenburns Image Gallery * Original author: John [at] Toymakerlabs * Further changes, comments: [at]Toymakerlabs * Licensed under the MIT license * * Copyright (c) 2013 ToymakerLabs * Permission is hereby granted, free of charge, to any person obtaining a copy of this software * and associated documentation files (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, publish, distribute, * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: The above copyright notice and this * permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ ;(function ( $, window, document, undefined ) { /* Plugin Parameters ------------------------------------------------------------------------------------------------- */ var pluginName = 'Kenburns', defaults = { images:[], duration:400, fadeSpeed:500, scale:1, ease3d:'cubic-bezier(.81, 0, .26, 1)', onLoadingComplete:function(){}, onSlideComplete:function(){}, onListComplete:function(){}, getSlideIndex:function(){ return currentSlide; } }; var imagesObj = {}; var currentSlide = 0; function Plugin( element, options ) { this.element = element; this.options = $.extend( {}, defaults, options) ; this._defaults = defaults; this._name = pluginName; this.maxSlides = this.options.images.length; this.init(); } /* 1. Initialization ------------------------------------------------------------------------------------------------- */ /** * Init * Initial setup - dermines width, height, and adds the loading icon. */ Plugin.prototype.init = function () { var list = this.options.images; var that = this; this.width = $(this.element).width(); this.height = $(this.element).height(); this.has3d = has3DTransforms(); for (i in list) { imagesObj["image"+i] = {}; imagesObj["image"+i].loaded = false; this.attachImage(list[i], "image"+i , i); } var loader = $('<div/>'); loader.addClass('loader'); loader.css({'position':'absolute','z-index':10000}); $(this.element).prepend(loader); $(this.element).on('click', function(e){ if (that.options.urls && that.options.urls[currentSlide]){ window.open(that.options.urls[currentSlide]) } }) }; /* 2. Loading and Setup ------------------------------------------------------------------------------------------------- */ /** * Attach image * creates a wrapper div for the image along with the image tag. The reason for the additional * wrapper is that we are transitioning multiple properties at the same time: scale, position, and * opacity. But we want opacity to finish first. This function also determines if the browser * has 3d transform capabilities and initializes the starting CSS values. */ Plugin.prototype.attachImage = function(url,alt_text,index) { var that = this; //put the image in an empty div to separate the animation effects of fading and moving var wrapper = $('<div/>'); wrapper.attr('class','kb-slide'); wrapper.css({'opacity':0}); var img = $("<img />"); img.attr('src', url); img.attr('alt', alt_text); wrapper.html(img); //First check if the browser supports 3D transitions, initialize the CSS accordingly if(this.has3d) { img.css({'-webkit-transform-origin':'left top'}); img.css({'-moz-transform-origin':'left top'}); img.css({'-webkit-transform':'scale('+that.options.scale+') translate3d(0,0,0)'}); img.css({'-moz-transform':'scale('+that.options.scale+') translate3d(0,0,0)'}); } //Switch the transition to the 3d version if it does exist this.doTransition = (this.has3d)?this.transition3d:this.transition; //set up the image OBJ parameters - used to track loading and initial dimensions img.on('load', function() { imagesObj["image"+index].element = this; imagesObj["image"+index].loaded = true; imagesObj["image"+index].width = $(this).width(); imagesObj["image"+index].width = $(this).height(); that.insertAt(index,wrapper); that.resume(index); }); } /** * Resume * Resume will continue the transition after the stalled image loads * it also fires the complete action when the series of images finishes loading */ Plugin.prototype.resume = function(index){ //first image has loaded if(index == 0) { this.startTransition(0); $(this.element).find('.loader').hide(); } //if the next image hasnt loaded yet, but the transition has started, // this will match the image index to the image holding the transition. // it will then resume the transition. if(index == this.holdup) { $('#status').html(""); $(this.element).find('.loader').hide(); this.startTransition(this.holdup); } //if the last image in the set has loaded, add the images in order if(this.checkLoadProgress() == true) { //reset the opacities and z indexes except the last and first images $(this.element).find('.stalled').each(function(){ $(this).css({'opacity':1,'z-index':1}); $(this).removeClass('stalled'); }); //fire the complete thing this.options.onLoadingComplete(); } } //if any of the slides are not loaded, the set has not finished loading. Plugin.prototype.checkLoadProgress = function() { var imagesLoaded = true; for(i=0;i<this.maxSlides;i++){ if (imagesObj["image"+i].loaded == false){ imagesLoaded = false; } } return imagesLoaded; } /** * Wait * Stops the transition interval, shows the loader and * applies the stalled class to the visible image. */ Plugin.prototype.wait = function() { clearInterval(this.interval); $('#status').html("loading"); $(this.element).find('.loader').show(); var image = imagesObj["image"+(currentSlide-1)].element; $(image).parent().stop(true,true); $(image).parent().addClass('stalled'); } /* 3. Transitions and Movement ------------------------------------------------------------------------------------------------- */ /** * startTransition * Begins the Gallery Transition and tracks the current slide * Also manages loading - if the interval encounters a slide * that has not loaded, the transition pauses. */ Plugin.prototype.startTransition = function(start_index) { var that = this; currentSlide = start_index; //current slide that.element.style.cursor = (that.options.urls && that.options.urls[currentSlide])? 'pointer' : 'auto' that.doTransition(); this.interval = setInterval(function(){ //Advance the current slide if(currentSlide < that.maxSlides-1){ currentSlide++; }else { currentSlide = 0; } that.element.style.cursor = (that.options.urls && that.options.urls[currentSlide])? 'pointer' : 'auto' //Check if the next slide is loaded. If not, wait. if(imagesObj["image"+currentSlide].loaded == false){ that.holdup = currentSlide; that.wait(); //if the next slide is loaded, go ahead and do the transition. }else { that.doTransition(); } },this.options.duration); } /** * chooseCorner * This function chooses a random start corner and a random end corner * that is different from the start. This gives a random direction effect * it returns coordinates used by the transition functions. */ Plugin.prototype.chooseCorner = function() { var scale = this.options.scale; var image = imagesObj["image"+currentSlide].element; var ratio = image.height/image.width; var sw = Math.floor($(this.element).width()*(1/scale)); var sh = Math.floor($(this.element).width()*ratio*(1/scale)); $(image).width(sw); $(image).height(sh); var w = $(this.element).width(); var h = $(this.element).height(); //console.log(sw+ ", " + this.width); var corners = [ {x:0,y:0}, {x:1,y:0}, {x:0,y:1}, {x:1,y:1} ]; //Pick the first corner. Remove it from the array var choice = Math.floor(Math.random()*4); var start = corners[choice]; //Pick the second corner from the subset corners.splice(choice,1); var end = corners[Math.floor(Math.random()*3)]; //build the new coordinates from the chosen coordinates var coordinates = { startX: start.x * (w - sw*scale) , startY: start.y * (h - sh*scale), endX: end.x * (w - sw), endY: end.y * (h - sh) } // // console.log(coordinates.startX + " , "+coordinates.startY + " , " +coordinates.endX + " , " +coordinates.endY); return coordinates; } /** * Transiton3D * Transition3d Function works by setting the webkit and moz translate3d properties. These * are hardware accellerated and give a very smooth animation. Since only one animation * can be applied at a time, I wrapped the images in a div. The shorter fade is applied to * the parent, while the translation and scaling is applied to the image. */ Plugin.prototype.transition3d = function () { var that = this; var scale = this.options.scale; var image = imagesObj["image"+currentSlide].element; var position = this.chooseCorner(); //First clear any existing transition $(image).css({'-webkit-transition':'none'}); $(image).css({'-moz-transition':'none'}); $(image).css({'-webkit-transform':'scale('+scale+') translate3d('+position.startX+'px,'+position.startY+'px,0)'}); $(image).css({'-moz-transform':'scale('+scale+') translate3d('+position.startX+'px,'+position.startY+'px,0)'}); //Set the wrapper to fully transparent and start it's animation $(image).parent().css({'opacity':0,'z-index':'3'}); $(image).parent().animate({'opacity':1},that.options.fadeSpeed); //Add the transition back in $(image).css({'-webkit-transition':'-webkit-transform '+(that.options.duration+that.options.fadeSpeed)+'ms '+that.options.ease3d}); $(image).css({'-moz-transition':'-moz-transform '+(that.options.duration+that.options.fadeSpeed)+'ms '+that.options.ease3d}); //set the end position and scale, which fires the transition $(image).css({'-webkit-transform':'scale(1) translate3d('+position.endX+'px,'+position.endY+'px,0)'}); $(image).css({'-moz-transform':'scale(1) translate3d('+position.endX+'px,'+position.endY+'px,0)'}); this.transitionOut(); this.options.onSlideComplete(); } /** * Transition * The regular JQuery animation function. Sets the currentSlide initial scale and position to * the value from chooseCorner before triggering the animation. It starts the image moving to * the new position, starts the fade on the wrapper, and delays the fade out animation. Adding * fadeSpeed to duration gave me a nice crossfade so the image continues to move as it fades out * rather than just stopping. */ Plugin.prototype.transition = function() { var that = this; var scale = this.options.scale; var image = imagesObj["image"+currentSlide].element; var sw = $(image).width(); var sh = $(image).height(); var position = this.chooseCorner(); $(image).css({'left':position.startX,'top':position.startY,'width':sw*(scale),'height':sh*(scale)}); $(image).animate({'left':position.endX,'top':position.endY,'width':sw,'height':sh}, that.options.duration + that.options.fadeSpeed); $(image).parent().css({'opacity':0,'z-index':3}); $(image).parent().animate({'opacity':1},that.options.fadeSpeed); this.transitionOut(); this.options.onSlideComplete(); } Plugin.prototype.transitionOut = function() { var that = this; var image = imagesObj["image"+currentSlide].element; $(image).parent().delay(that.options.duration).animate({'opacity':0},that.options.fadeSpeed, function(){ $(this).css({'z-index':1}); }); } /* 4. Utility Functions ------------------------------------------------------------------------------------------------- */ /** * has3DTransforms * Tests the browser to determine support for Webkit and Moz Transforms * Creates an element, translates the element, and tests the values. If the * values return true, the browser supports 3D transformations. */ function has3DTransforms() { var el = document.createElement('p'), has3d, transforms = { 'WebkitTransform':'-webkit-transform', 'MozTransform':'-moz-transform', }; document.body.insertBefore(el, null); for (var t in transforms) { if (el.style[t] !== undefined) { el.style[t] = "translate3d(1px,1px,1px)"; has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]); } } document.body.removeChild(el); return (has3d !== undefined && has3d.length > 0 && has3d !== "none"); } /** * insertAt * Utility function that inserts objects at a specific index * Used to maintain the order of images as they are loaded and * added to the DOM */ Plugin.prototype.insertAt = function (index, element) { var lastIndex = $(this.element).children().length; if (index < 0) { index = Math.max(0, lastIndex + 1 + index); } var imgWrapper = $(this.element).append(element); if (index < lastIndex) { $(this.element).children().eq(index).before($(this.element).children().last()); } } $.fn[pluginName] = function ( options ) { return this.each(function () { if (!$.data(this, 'plugin_' + pluginName)) { $.data(this, 'plugin_' + pluginName, new Plugin( this, options )); } }); } })( jQuery, window, document );