/* * Author: Marco Kuiper (http://www.marcofolio.net/) */ (function($){ $.jfancytile = function(el, options){ var base = this; base.$el = $(el); base.el = el; base.$el.data("jfancytile", base); base.init = function(){ base.options = $.extend({},$.jfancytile.defaultOptions, options); // Safari and Chrome load JS and CSS parallel. Therefor, image size can be wrong // since the JS can be finished, while the CSS isn't. The following lines waits // until the CSS is ready, so we can retrieve the correct data. // via StackOverflow: http://tinyurl.com/kp6lqj // if (jQuery.browser.safari && document.readyState != "complete"){ // setTimeout( arguments.callee, 100 ); // return; // } // Calculate the max container dimensions // and save the image data var imageData = { }; var container = { width : 0, height : 0 }; base.imageCounter = 0; $("ul li img", base.$el).each(function() { // Retrieve the image data imageData[base.imageCounter] = { src : $(this).attr("src"), title : $(this).attr("alt"), width : $(this).width(), height : $(this).height() }; base.imageCounter++; // Get the max container dimensions if( $(this).width() > container.width ) { container.width = $(this).width(); } if( $(this).height() > container.height ) { container.height = $(this).height(); } }); // Remove all list items $("ul", base.$el).remove(); // Create backwards navigation var navBack = $("
") .attr("class", "jfancytilenav jfancytileBack") .css({ height : container.height }) .click(function(){ navigate("back"); }) .appendTo(base.$el); // Create forwards navigation var navForward = $("
") .attr("class", "jfancytilenav jfancytileForward") .css({ "height" : container.height, "margin-left" : container.width - 50, }) .click(function(){ navigate("forward"); }) .appendTo(base.$el); // Create host container var hostContainer = $("
") .attr("class", "jfancytileContainer") .css({ width : container.width, height : container.height }) .appendTo(base.$el); // Calculate the number of tiles needed var totalNrOfTiles = base.options.rowCount * base.options.columnCount; // Create the tiles var first = true; for(var img in imageData) { // Create image container var imageContainer = $("
") .css({ "width" : imageData[img].width, "height" : imageData[img].height, "position" : "absolute", }); // Position it in the center of the container if(imageData[img].width < container.width) { var margin = Math.floor((container.width - imageData[img].width) / 2); imageContainer.css({ "margin-left" : margin + "px" }); } if(imageData[img].height < container.height) { var margin = Math.floor((container.height - imageData[img].height) / 2); imageContainer.css({ "margin-top" : margin + "px" }); } // Easy handler for the first, since we need to hide the others if(first) { imageContainer.attr("class", "jfancyfirst"); first = false; } imageContainer.appendTo($(hostContainer)); // Append the title var titleContainer = $("

") .html(imageData[img].title) .attr("class", "jfancytileTitle") .appendTo($(imageContainer)); // Calculate tile size var tileDimension = { width : Math.floor((imageData[img].width / base.options.columnCount)), height : Math.floor((imageData[img].height / base.options.rowCount)) }; // Create the tiles // Take note we record at which row and column we are, since we need to position the background position for each tile seperately var tilePosition = { x : 0, y : 0 }; for(var i = 0; i < totalNrOfTiles; i++) { var tile = $("
") .css({ "float" : "left", "position" : "relative", "width" : tileDimension.width, "height" : tileDimension.height, "background-image" : "url(" + imageData[img].src + ")", "background-position" : "-" + (tilePosition.x * tileDimension.width) + "px -" + (tilePosition.y * tileDimension.height) + "px" }) .appendTo($(imageContainer)); tilePosition.x++; if(tilePosition.x > base.options.columnCount - 1) { // Minus one, since tilePosition is zero based tilePosition.x = 0; tilePosition.y++; } } }; // Hide all the images, except the first one base.$el.children().not("div.jfancytilenav").children().not(".jfancyfirst").children().not("h3").each(function() { // Place on random position var amount = Math.floor(Math.random() * base.options.maxTileShift+1); var tileDimension = { width : $(this).width() * amount, height : $(this).height() * amount }; // Place on a random direction var direction = Math.floor(Math.random() * 4); switch (direction) { case 0: $(this).css({ top: tileDimension.height, opacity : 0 }); break; case 1: $(this).css({ left: tileDimension.width, opacity : 0 }); break; case 2: $(this).css({ top: '-' + tileDimension.height + 'px', opacity : 0 }); break; case 3: $(this).css({ left: '-' + tileDimension.width + 'px', opacity : 0 }); break; } }); base.$el.children().not("div.jfancytilenav").children().not(".jfancyfirst").children().not("div").fadeOut(0); }; var currentZindex = 1; var currentImageIndex = 0; var navigate = function(direction){ // Search for the tiles we need to animate, by searching from the root base.$el.children().not("div.jfancytilenav").children().eq(currentImageIndex).children().not("h3").each(function() { // The tiles should only move a maximum of 'maxTileShift' times their dimension var amount = Math.floor(Math.random() * base.options.maxTileShift+1); var tileDimension = { width : $(this).width() * amount, height : $(this).height() * amount }; // Animate to a random direction var direction = Math.floor(Math.random() * 4); switch (direction) { case 0: $(this).animate({ top: '+=' + tileDimension.height, opacity:0 }, base.options.outSpeed, base.options.outEasing); break; case 1: $(this).animate({ left: '+=' + tileDimension.width, opacity:0 }, base.options.outSpeed, base.options.outEasing); break; case 2: $(this).animate({ top: '-=' + tileDimension.height, opacity:0 }, base.options.outSpeed, base.options.outEasing); break; case 3: $(this).animate({ left: '-=' + tileDimension.width, opacity:0 }, base.options.outSpeed, base.options.outEasing); break; } }); // Fade out the title base.$el.children().not("div.jfancytilenav").children().eq(currentImageIndex).children().not("div").fadeOut(base.options.outSpeed); // Show the next image based on the direction // We also check if we're at the end of the slideshow and show the first one // if we're at the first one and navigating back, we show the last one etc. if(direction == "back") { if(currentImageIndex != 0) { currentImageIndex--; } else { currentImageIndex = base.imageCounter -1; } } else if (direction == "forward") { if(currentImageIndex != base.imageCounter - 1) { // Minus one, zero based currentImageIndex++; } else { currentImageIndex = 0; } } // Bring the container to the foreground currentZindex++; base.$el.children().not("div.jfancytilenav").children().eq(currentImageIndex).css({ "z-index" : currentZindex }); base.$el.children().not("div.jfancytilenav").children().eq(currentImageIndex).children().not("h3").each(function() { // Animate them back $(this).animate({ top : 0, left:0, opacity:1 }, base.options.inSpeed, base.options.inEasing); }); base.$el.children().not("div.jfancytilenav").children().eq(currentImageIndex).children().not("div").fadeIn(base.options.inSpeed); }; // Run initializer base.init(); }; $.jfancytile.defaultOptions = { inEasing: "swing", outEasing: "swing", inSpeed: 1000, outSpeed: 1000, rowCount: 8, columnCount: 13, maxTileShift: 3 }; $.fn.jfancytile = function(options){ return this.each(function(){ (new $.jfancytile(this, options)); }); }; })(jQuery);