├── README.md ├── jquery.500px.layout.js ├── jquery.500px.layout.min.js └── style.css /README.md: -------------------------------------------------------------------------------- 1 | jquery-500px-layout 2 | =================== 3 | 4 | Jquery implementation of the old 500px layout: 5 | 6 | Credits and the detailed explanation: 7 | http://blog.vjeux.com/2012/image/image-layout-algorithm-500px.html 8 | 9 | This plugin is used on the landing page of: 10 | http://www.estudiovicencio.cl/ 11 | 12 | ## Usage 13 | 14 | ```javascript 15 | $(function () { 16 | $("#layout").layout({ 17 | patterns: ['o|--o|oo','|--o|o--','--o|ooo|','oo|o--|o'], 18 | specialPatterns: ['----','----','--oo','oooo','|--o|o--','o|--o|oo'], 19 | blockFillEl: $('') 20 | }); 21 | }) 22 | ``` 23 | ### Options 24 | 25 | `patterns`: an array of string with the patterns to be repeatedly used. All available combinations are here http://jsfiddle.net/vjeux/L2NQ6 (credits to blog.vjeux.com). By default `["##--##oo"]` 26 | 27 | `specialPatterns`: are used on the ending conditions, each element from the array is used when remains 1,2,3,4 or 6 elements. By default `[]` 28 | 29 | `blockEl`: The element to be transformed. By default `"i"`, 30 | 31 | `blockFillEl`: a fill element used when in the last row there is only one element 32 | 33 | -------------------------------------------------------------------------------- /jquery.500px.layout.js: -------------------------------------------------------------------------------- 1 | +function ($) { 2 | 3 | "use strict"; 4 | 5 | window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame 6 | || function(callback){ window.setTimeout(callback, 1000 / 60);}; 7 | 8 | var Layout = function (element, options) { 9 | var self = this; 10 | this.$el = $(element); 11 | this.opts = $.extend({}, Layout.DEFAULTS, options); 12 | this.elementWidth = this.$el.width(); 13 | 14 | $(window).resize(function (){ 15 | this.resizeTo && clearTimeout(this.resizeWatcher); 16 | this.resizeWatcher = setTimeout(function() { 17 | $(this).trigger('v.resize'); 18 | }, 400); 19 | }); 20 | 21 | $(window).on('v.resize', function () { 22 | var currentWidth = self.$el.width(); 23 | if (self.elementWidth !== currentWidth) { 24 | self.elementWidth = currentWidth; 25 | requestAnimationFrame(function () { 26 | self.render(); 27 | }); 28 | } 29 | }); 30 | } 31 | 32 | Layout.DEFAULTS = { 33 | margin: 12, //pixels 34 | blockEl: 'i', 35 | patterns: ['##--##oo'], 36 | specialPatterns: [] 37 | } 38 | 39 | Layout.prototype.setBlockWidth = function (size) { 40 | this.blockWidth = size ? size : (this.$el.innerWidth() - 4 * this.opts.margin) / 4; 41 | return this; 42 | } 43 | 44 | Layout.prototype.setBlocks = function () { 45 | this.blocks = this.$el.find(this.opts.blockEl).get().reverse(); 46 | return this; 47 | } 48 | 49 | Layout.prototype.renderBlock = function (x, y, width, height) { 50 | var margin = this.opts.margin, 51 | size = this.blockWidth, 52 | block = this.blocks.pop(); 53 | 54 | if(block !== undefined) { 55 | $(block).css({ 56 | 'margin-left': x * size + (x + 1) * margin, 57 | 'margin-top': y * size + (y + 1) * margin, 58 | 'width': width * size + (width - 1) * margin, 59 | 'height': Math.ceil(height * size + (height - 1) * margin), 60 | 'display': 'inline' 61 | }); 62 | } 63 | return this; 64 | } 65 | 66 | Layout.prototype.renderCanvas = function (height, pattern) { 67 | 68 | for (var i = 0, ll = pattern.length; i < ll; i++) { 69 | 70 | var x = i % 4, 71 | y = height + Math.floor(i / 4); 72 | 73 | if (pattern[i] === 'o') { 74 | this.renderBlock(x, y, 1, 1); 75 | 76 | } else if (pattern[i] === '#') { 77 | this.renderBlock(x, y, 2, 2); 78 | pattern[i] = pattern[i + 1] = pattern[i + 4] = pattern[i + 5] = 'x'; 79 | 80 | } else if (pattern[i] === '|') { 81 | this.renderBlock(x, y, 1, 2); 82 | pattern[i] = pattern[i + 4] = 'x'; 83 | 84 | } else if (pattern[i] === '-') { 85 | this.renderBlock(x, y, 2, 1); 86 | pattern[i] = pattern[i + 1] = 'x'; 87 | } 88 | } 89 | return this; 90 | } 91 | 92 | Layout.prototype.render = function () { 93 | 94 | this.setBlocks().setBlockWidth(); 95 | 96 | var h = 0, 97 | i = 0, 98 | lastEl; 99 | 100 | while (this.blocks.length) { 101 | 102 | var nBlocks = this.blocks.length, 103 | pattern = ''; 104 | 105 | if (nBlocks === 1) { 106 | this.$el.append(this.opts.blockFillEl); 107 | this.blocks.push(this.opts.blockFillEl); 108 | 109 | this.blocks[1] = this.blocks[0]; 110 | this.blocks[0] = this.opts.blockFillEl; 111 | } 112 | 113 | if (nBlocks < 6 && this.opts.specialPatterns[nBlocks-1]) { 114 | pattern = this.opts.specialPatterns[nBlocks-1]; 115 | } else { 116 | pattern = this.opts.patterns[i]; 117 | } 118 | 119 | this.renderCanvas(h, pattern.split('')); 120 | 121 | i = (i + 2) === (this.opts.patterns.length) ? 0 : (i + 1); 122 | h += 2; 123 | } 124 | 125 | /* fix the height */ 126 | lastEl = $('i:last'); 127 | this.$el.height(parseInt(lastEl.css('height')) + parseInt(lastEl.css('margin-top'))); 128 | } 129 | 130 | // MODAL PLUGIN DEFINITION 131 | // ======================= 132 | 133 | $.fn.layout = function (option) { 134 | return this.each(function () { 135 | 136 | var $this = $(this), 137 | data = $this.data('layout'), 138 | options = $.extend({}, Layout.DEFAULTS, $this.data(), typeof option == 'object' && option) 139 | 140 | !data && $this.data('layout', (data = new Layout(this, options))); 141 | 142 | requestAnimationFrame(function () { 143 | $this.data('layout').render(); 144 | }); 145 | 146 | }); 147 | } 148 | $.fn.layout.Constructor = Layout; 149 | }(window.jQuery); 150 | -------------------------------------------------------------------------------- /jquery.500px.layout.min.js: -------------------------------------------------------------------------------- 1 | +function(e){"use strict";window.requestAnimationFrame=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame||function(e){window.setTimeout(e,1e3/60)};var t=function(n,r){var i=this;this.$el=e(n);this.opts=e.extend({},t.DEFAULTS,r);this.elementWidth=this.$el.width();e(window).resize(function(){this.resizeTo&&clearTimeout(this.resizeWatcher);this.resizeWatcher=setTimeout(function(){e(this).trigger("v.resize")},400)});e(window).on("v.resize",function(){var e=i.$el.width();if(i.elementWidth!==e){i.elementWidth=e;requestAnimationFrame(function(){i.render()})}})};t.DEFAULTS={margin:12,blockEl:"i",patterns:["##--##oo"],specialPatterns:[]};t.prototype.setBlockWidth=function(e){this.blockWidth=e?e:(this.$el.innerWidth()-4*this.opts.margin)/4;return this};t.prototype.setBlocks=function(){this.blocks=this.$el.find(this.opts.blockEl).get().reverse();return this};t.prototype.renderBlock=function(t,n,r,i){var s=this.opts.margin,o=this.blockWidth,u=this.blocks.pop();if(u!==undefined){e(u).css({"margin-left":t*o+(t+1)*s,"margin-top":n*o+(n+1)*s,width:r*o+(r-1)*s,height:Math.ceil(i*o+(i-1)*s),display:"inline"})}return this};t.prototype.renderCanvas=function(e,t){for(var n=0,r=t.length;n