78 | If you have the image sizes in the image element e.g. <img src="myimage.jpg" width="100" height="50" />
79 | then you don't need to load all images first for the plugin to work i.e. $(window).load(... is not required.
80 | This demo has a simulated loading delay on images to show what happens. Please note that you will need all images sizes. Miss one and it won't work.
81 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/jquery.collagePlus.js:
--------------------------------------------------------------------------------
1 | /*!
2 | *
3 | * jQuery collagePlus Plugin v0.3.3
4 | * https://github.com/ed-lea/jquery-collagePlus
5 | *
6 | * Copyright 2012, Ed Lea twitter.com/ed_lea
7 | *
8 | * built for http://qiip.me
9 | *
10 | * Dual licensed under the MIT or GPL Version 2 licenses.
11 | * http://www.opensource.org/licenses/mit-license.php
12 | * http://www.opensource.org/licenses/GPL-2.0
13 | *
14 | */
15 |
16 |
17 |
18 |
19 |
20 | ;(function( $ ) {
21 |
22 |
23 | $.fn.collagePlus = function( options ) {
24 |
25 | return this.each(function() {
26 |
27 | /*
28 | *
29 | * set up vars
30 | *
31 | */
32 |
33 | // track row width by adding images, padding and css borders etc
34 | var row = 0,
35 | // collect elements to be re-sized in current row
36 | elements = [],
37 | // track the number of rows generated
38 | rownum = 1,
39 | // needed for creating some additional defaults that are actually obtained
40 | // from the dom, which maybe doesn't make them defaults ?!
41 | $this = $(this);
42 |
43 |
44 | // width of the area the collage will be in
45 | $.fn.collagePlus.defaults.albumWidth = $this.width();
46 | // padding between the images. Using padding left as we assume padding is even all the way round
47 | $.fn.collagePlus.defaults.padding = parseFloat( $this.css('padding-left') );
48 | // object that contains the images to collage
49 | $.fn.collagePlus.defaults.images = $this.children();
50 |
51 | var settings = $.extend({}, $.fn.collagePlus.defaults, options);
52 |
53 | settings.images.each(
54 | function(index){
55 |
56 | /*
57 | *
58 | * Cache selector
59 | * Even if first child is not an image the whole sizing is based on images
60 | * so where we take measurements, we take them on the images
61 | *
62 | */
63 | var $this = $(this),
64 | $img = ($this.is("img")) ? $this : $(this).find("img");
65 |
66 |
67 |
68 | /*
69 | *
70 | * get the current image size. Get image size in this order
71 | *
72 | * 1. from tag
73 | * 2. from data set from initial calculation
74 | * 3. after loading the image and checking it's actual size
75 | *
76 | */
77 | var w = (typeof $img.data("width") != 'undefined') ? $img.data("width") : $img.width(),
78 | h = (typeof $img.data("height") != 'undefined') ? $img.data("height") : $img.height();
79 |
80 |
81 |
82 | /*
83 | *
84 | * Get any current additional properties that may affect the width or height
85 | * like css borders for example
86 | *
87 | */
88 | var imgParams = getImgProperty($img);
89 |
90 |
91 | /*
92 | *
93 | * store the original size for resize events
94 | *
95 | */
96 | $img.data("width", w);
97 | $img.data("height", h);
98 |
99 |
100 |
101 | /*
102 | *
103 | * calculate the w/h based on target height
104 | * this is our ideal size, but later we'll resize to make it fit
105 | *
106 | */
107 | var nw = Math.ceil(w/h*settings.targetHeight),
108 | nh = Math.ceil(settings.targetHeight);
109 |
110 | /*
111 | *
112 | * Keep track of which images are in our row so far
113 | *
114 | */
115 | elements.push([this, nw, nh, imgParams['w'], imgParams['h']]);
116 |
117 | /*
118 | *
119 | * calculate the width of the element including extra properties
120 | * like css borders
121 | *
122 | */
123 | row += nw + imgParams['w'] + settings.padding;
124 |
125 | /*
126 | *
127 | * if the current row width is wider than the parent container
128 | * it's time to make a row out of our images
129 | *
130 | */
131 | if( row > settings.albumWidth && elements.length != 0 ){
132 |
133 | // call the method that calculates the final image sizes
134 | // remove one set of padding as it's not needed for the last image in the row
135 | resizeRow(elements, (row - settings.padding), settings, rownum);
136 |
137 | // reset our row
138 | delete row;
139 | delete elements;
140 | row = 0;
141 | elements = [];
142 | rownum += 1;
143 | }
144 |
145 |
146 | /*
147 | *
148 | * if the images left are not enough to make a row
149 | * then we'll force them to make one anyway
150 | *
151 | */
152 | if ( settings.images.length-1 == index && elements.length != 0){
153 | resizeRow(elements, row, settings, rownum);
154 |
155 | // reset our row
156 | delete row;
157 | delete elements;
158 | row = 0;
159 | elements = [];
160 | rownum += 1;
161 | }
162 | }
163 | );
164 |
165 | });
166 |
167 | function resizeRow( obj, row, settings, rownum) {
168 |
169 | /*
170 | *
171 | * How much bigger is this row than the available space?
172 | * At this point we have adjusted the images height to fit our target height
173 | * so the image size will already be different from the original.
174 | * The resizing we're doing here is to adjust it to the album width.
175 | *
176 | * We also need to change the album width (basically available space) by
177 | * the amount of padding and css borders for the images otherwise
178 | * this will skew the result.
179 | *
180 | * This is because padding and borders remain at a fixed size and we only
181 | * need to scale the images.
182 | *
183 | */
184 | var imageExtras = (settings.padding * (obj.length - 1)) + (obj.length * obj[0][3]),
185 | albumWidthAdjusted = settings.albumWidth - imageExtras,
186 | overPercent = albumWidthAdjusted / (row - imageExtras),
187 | // start tracking our width with know values that will make up the total width
188 | // like borders and padding
189 | trackWidth = imageExtras,
190 | // guess whether this is the last row in a set by checking if the width is less
191 | // than the parent width.
192 | lastRow = (row < settings.albumWidth ? true : false);
193 |
194 |
195 |
196 |
197 |
198 | /*
199 | * Resize the images by the above % so that they'll fit in the album space
200 | */
201 | for (var i = 0; i < obj.length; i++) {
202 |
203 |
204 |
205 | var $obj = $(obj[i][0]),
206 | fw = Math.floor(obj[i][1] * overPercent),
207 | fh = Math.floor(obj[i][2] * overPercent),
208 | // if the element is the last in the row,
209 | // don't apply right hand padding (this is our flag for later)
210 | isNotLast = !!(( i < obj.length - 1 ));
211 |
212 | /*
213 | * Checking if the user wants to not stretch the images of the last row to fit the
214 | * parent element size
215 | */
216 | if(settings.allowPartialLastRow === true && lastRow === true){
217 | fw = obj[i][1];
218 | fh = obj[i][2];
219 | }
220 |
221 |
222 | /*
223 | *
224 | * Because we use % to calculate the widths, it's possible that they are
225 | * a few pixels out in which case we need to track this and adjust the
226 | * last image accordingly
227 | *
228 | */
229 | trackWidth += fw;
230 |
231 |
232 | /*
233 | *
234 | * here we check if the combined images are exactly the width
235 | * of the parent. If not then we add a few pixels on to make
236 | * up the difference.
237 | *
238 | * This will alter the aspect ratio of the image slightly, but
239 | * by a noticable amount.
240 | *
241 | * If the user doesn't want full width last row, we check for that here
242 | *
243 | */
244 | if(!isNotLast && trackWidth < settings.albumWidth){
245 | if(settings.allowPartialLastRow === true && lastRow === true){
246 | fw = fw;
247 | }else{
248 | fw = fw + (settings.albumWidth - trackWidth);
249 | }
250 | }
251 |
252 | fw--;
253 |
254 | /*
255 | *
256 | * We'll be doing a few things to the image so here we cache the image selector
257 | *
258 | *
259 | */
260 | var $img = ( $obj.is("img") ) ? $obj : $obj.find("img");
261 |
262 | /*
263 | *
264 | * Set the width of the image and parent element
265 | * if the resized element is not an image, we apply it to the child image also
266 | *
267 | * We need to check if it's an image as the css borders are only measured on
268 | * images. If the parent is a div, we need make the contained image smaller
269 | * to accommodate the css image borders.
270 | *
271 | */
272 | $img.width(fw);
273 | if( !$obj.is("img") ){
274 | $obj.width(fw + obj[i][3]);
275 | }
276 |
277 |
278 | /*
279 | *
280 | * Set the height of the image
281 | * if the resized element is not an image, we apply it to the child image also
282 | *
283 | */
284 | $img.height(fh);
285 | if( !$obj.is("img") ){
286 | $obj.height(fh + obj[i][4]);
287 | }
288 |
289 |
290 | /*
291 | *
292 | * Apply the css extras like padding
293 | *
294 | */
295 | applyModifications($obj, isNotLast, settings);
296 |
297 |
298 | /*
299 | *
300 | * Assign the effect to show the image
301 | * Default effect is using jquery and not CSS3 to support more browsers
302 | * Wait until the image is loaded to do this
303 | *
304 | */
305 |
306 | $img
307 | .one('load', function (target) {
308 | return function(){
309 | if( settings.effect == 'default'){
310 | target.animate({opacity: '1'},{duration: settings.fadeSpeed});
311 | } else {
312 | if(settings.direction == 'vertical'){
313 | var sequence = (rownum <= 10 ? rownum : 10);
314 | } else {
315 | var sequence = (i <= 9 ? i+1 : 10);
316 | }
317 | /* Remove old classes with the "effect-" name */
318 | target.removeClass(function (index, css) {
319 | return (css.match(/\beffect-\S+/g) || []).join(' ');
320 | });
321 | target.addClass(settings.effect);
322 | target.addClass("effect-duration-" + sequence);
323 | }
324 | }
325 | }($obj))
326 | /*
327 | * fix for cached or loaded images
328 | * For example if images are loaded in a "window.load" call we need to trigger
329 | * the load call again
330 | */
331 | .each(function() {
332 | if(this.complete) $(this).trigger('load');
333 | });
334 |
335 | }
336 |
337 |
338 |
339 |
340 |
341 | }
342 |
343 | /*
344 | *
345 | * This private function applies the required css to space the image gallery
346 | * It applies it to the parent element so if an image is wrapped in a
then
347 | * the css is applied to the
348 | *
349 | */
350 | function applyModifications($obj, isNotLast, settings) {
351 | var css = {
352 | // Applying padding to element for the grid gap effect
353 | 'margin-bottom' : settings.padding + "px",
354 | 'margin-right' : (isNotLast) ? settings.padding + "px" : "0px",
355 | // Set it to an inline-block by default so that it doesn't break the row
356 | 'display' : settings.display,
357 | // Set vertical alignment otherwise you get 4px extra padding
358 | 'vertical-align' : "bottom",
359 | // Hide the overflow to hide the caption
360 | 'overflow' : "hidden"
361 | };
362 |
363 | return $obj.css(css);
364 | }
365 |
366 |
367 | /*
368 | *
369 | * This private function calculates any extras like padding, border associated
370 | * with the image that will impact on the width calculations
371 | *
372 | */
373 | function getImgProperty( img )
374 | {
375 | $img = $(img);
376 | var params = new Array();
377 | params["w"] = (parseFloat($img.css("border-left-width")) + parseFloat($img.css("border-right-width")));
378 | params["h"] = (parseFloat($img.css("border-top-width")) + parseFloat($img.css("border-bottom-width")));
379 | return params;
380 | }
381 |
382 | };
383 |
384 | $.fn.collagePlus.defaults = {
385 | // the ideal height you want your images to be
386 | 'targetHeight' : 400,
387 | // how quickly you want images to fade in once ready can be in ms, "slow" or "fast"
388 | 'fadeSpeed' : "fast",
389 | // how the resized block should be displayed. inline-block by default so that it doesn't break the row
390 | 'display' : "inline-block",
391 | // which effect you want to use for revealing the images (note CSS3 browsers only),
392 | 'effect' : 'default',
393 | // effect delays can either be applied per row to give the impression of descending appearance
394 | // or horizontally, so more like a flock of birds changing direction
395 | 'direction' : 'vertical',
396 | // Sometimes there is just one image on the last row and it gets blown up to a huge size to fit the
397 | // parent div width. To stop this behaviour, set this to true
398 | 'allowPartialLastRow' : false
399 | };
400 |
401 | })( jQuery );
402 |
--------------------------------------------------------------------------------