1/* Snowfall jquery plugin 2 3 ==================================================================== 4 LICENSE 5 ==================================================================== 6 Licensed under the Apache License, Version 2.0 (the "License"); 7 you may not use this file except in compliance with the License. 8 You may obtain a copy of the License at 9 10 http://www.apache.org/licenses/LICENSE-2.0 11 12 Unless required by applicable law or agreed to in writing, software 13 distributed under the License is distributed on an "AS IS" BASIS, 14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 See the License for the specific language governing permissions and 16 limitations under the License. 17 ==================================================================== 18 19 Version 1.51 Dec 2nd 2012 20 // fixed bug where snow collection didn't happen if a valid doctype was declared. 21 22 Version 1.5 Oct 5th 2011 23 Added collecting snow! Uses the canvas element to collect snow. In order to initialize snow collection use the following 24 25 $(document).snowfall({collection : 'element'}); 26 27 element = any valid jquery selector. 28 29 The plugin then creates a canvas above every element that matches the selector, and collects the snow. If there are a varrying amount of elements the 30 flakes get assigned a random one on start they will collide. 31 32 Version 1.4 Dec 8th 2010 33 Fixed issues (I hope) with scroll bars flickering due to snow going over the edge of the screen. 34 Added round snowflakes via css, will not work for any version of IE. - Thanks to Luke Barker of http://www.infinite-eye.com/ 35 Added shadows as an option via css again will not work with IE. The idea behind shadows, is to show flakes on lighter colored web sites - Thanks Yutt 36 37 Version 1.3.1 Nov 25th 2010 38 Updated script that caused flakes not to show at all if plugin was initialized with no options, also added the fixes that Han Bongers suggested 39 40 Developed by Jason Brown for any bugs or questions email me at loktar69@hotmail 41 info on the plugin is located on Somethinghitme.com 42 43 values for snow options are 44 45 flakeCount, 46 flakeColor, 47 flakeIndex, 48 minSize, 49 maxSize, 50 minSpeed, 51 maxSpeed, 52 round, true or false, makes the snowflakes rounded if the browser supports it. 53 shadow true or false, gives the snowflakes a shadow if the browser supports it. 54 55 Example Usage : 56 $(document).snowfall({flakeCount : 100, maxSpeed : 10}); 57 58 -or- 59 60 $('#element').snowfall({flakeCount : 800, maxSpeed : 5, maxSize : 5}); 61 62 -or with defaults- 63 64 $(document).snowfall(); 65 66 - To clear - 67 $('#element').snowfall('clear'); 68*/ 69 70// Paul Irish requestAnimationFrame polyfill 71(function () { 72 var lastTime = 0; 73 var vendors = ['webkit', 'moz']; 74 for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { 75 window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame']; 76 window.cancelAnimationFrame = 77 window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame']; 78 } 79 80 if (!window.requestAnimationFrame) 81 window.requestAnimationFrame = function (callback, element) { 82 var currTime = new Date().getTime(); 83 var timeToCall = Math.max(0, 16 - (currTime - lastTime)); 84 var id = window.setTimeout(function () { callback(currTime + timeToCall); }, 85 timeToCall); 86 lastTime = currTime + timeToCall; 87 return id; 88 }; 89 90 if (!window.cancelAnimationFrame) 91 window.cancelAnimationFrame = function (id) { 92 clearTimeout(id); 93 }; 94}()); 95 96(function ($) { 97 $.snowfall = function (element, options) { 98 var defaults = { 99 flakeCount: 35, 100 flakeColor: '#ffffff', 101 flakeIndex: 999999, 102 minSize: 1, 103 maxSize: 2, 104 minSpeed: 1, 105 maxSpeed: 5, 106 round: false, 107 shadow: false, 108 collection: false, 109 collectionHeight: 40, 110 deviceorientation: false 111 }, 112 options = $.extend(defaults, options), 113 random = function random(min, max) { 114 return Math.round(min + Math.random() * (max - min)); 115 }; 116 117 $(element).data("snowfall", this); 118 119 // Snow flake object 120 function Flake(_x, _y, _size, _speed, _id) { 121 // Flake properties 122 this.id = _id; 123 this.x = _x; 124 this.y = _y; 125 this.size = _size; 126 this.speed = _speed; 127 this.step = 0; 128 this.stepSize = random(1, 10) / 100; 129 130 if (options.collection) { 131 this.target = canvasCollection[random(0, canvasCollection.length - 1)]; 132 } 133 134 var flakeMarkup = null; 135 136 if (options.image) { 137 flakeMarkup = $(document.createElement("img")); 138 flakeMarkup[0].src = options.image; 139 } else { 140 flakeMarkup = $(document.createElement("div")); 141 flakeMarkup.css({ 'background': options.flakeColor }); 142 } 143 144 flakeMarkup.attr({ 'class': 'snowfall-flakes', 'id': 'flake-' + this.id }).css({ 'width': this.size, 'height': this.size, 'position': 'absolute', 'top': this.y, 'left': this.x, 'fontSize': 0, 'zIndex': options.flakeIndex }); 145 146 if ($(element).get(0).tagName === $(document).get(0).tagName) { 147 $('body').append(flakeMarkup); 148 element = $('body'); 149 } else { 150 $(element).append(flakeMarkup); 151 } 152 153 this.element = document.getElementById('flake-' + this.id); 154 155 // Update function, used to update the snow flakes, and checks current snowflake against bounds 156 this.update = function () { 157 this.y += this.speed; 158 159 if (this.y > (elHeight) - (this.size + 6)) { 160 this.reset(); 161 } 162 163 this.element.style.top = this.y + 'px'; 164 this.element.style.left = this.x + 'px'; 165 166 this.step += this.stepSize; 167 168 if (doRatio === false) { 169 this.x += Math.cos(this.step); 170 } else {
171 this.x += (doRatio + Math.cos(this.step)); 172 } 173 174 // Pileup check 175 if (options.collection) { 176 if (this.x > this.target.x && this.x < this.target.width + this.target.x && this.y > this.target.y && this.y < this.target.height + this.target.y) { 177 var ctx = this.target.element.getContext("2d"), 178 curX = this.x - this.target.x, 179 curY = this.y - this.target.y, 180 colData = this.target.colData; 181 182 if (colData[parseInt(curX)][parseInt(curY + this.speed + this.size)] !== undefined || curY + this.speed + this.size > this.target.height) { 183 if (curY + this.speed + this.size > this.target.height) { 184 while (curY + this.speed + this.size > this.target.height && this.speed > 0) { 185 this.speed *= .5; 186 } 187 188 ctx.fillStyle = "#fff"; 189 190 if (colData[parseInt(curX)][parseInt(curY + this.speed + this.size)] == undefined) { 191 colData[parseInt(curX)][parseInt(curY + this.speed + this.size)] = 1; 192 ctx.fillRect(curX, (curY) + this.speed + this.size, this.size, this.size); 193 } else { 194 colData[parseInt(curX)][parseInt(curY + this.speed)] = 1; 195 ctx.fillRect(curX, curY + this.speed, this.size, this.size); 196 } 197 this.reset(); 198 } else { 199 // flow to the sides 200 this.speed = 1; 201 this.stepSize = 0; 202 203 if (parseInt(curX) + 1 < this.target.width && colData[parseInt(curX) + 1][parseInt(curY) + 1] == undefined) { 204 // go left 205 this.x++; 206 } else if (parseInt(curX) - 1 > 0 && colData[parseInt(curX) - 1][parseInt(curY) + 1] == undefined) { 207 // go right 208 this.x--; 209 } else { 210 //stop 211 ctx.fillStyle = "#fff"; 212 ctx.fillRect(curX, curY, this.size, this.size); 213 colData[parseInt(curX)][parseInt(curY)] = 1; 214 this.reset(); 215 } 216 } 217 } 218 } 219 } 220 221 if (this.x > (elWidth) - widthOffset || this.x < widthOffset) { 222 this.reset(); 223 } 224 } 225 226 // Resets the snowflake once it reaches one of the bounds set 227 this.reset = function () { 228 this.y = 0; 229 this.x = random(widthOffset, elWidth - widthOffset); 230 this.stepSize = random(1, 10) / 100; 231 this.size = random((options.minSize * 100), (options.maxSize * 100)) / 100; 232 this.speed = random(options.minSpeed, options.maxSpeed); 233 } 234 } 235 236 // local vars 237 var flakes = [], 238 flakeId = 0, 239 i = 0, 240 elHeight = $(element).height(), 241 elWidth = $(element).width(), 242 widthOffset = 0, 243 snowTimeout = 0; 244 245 // Collection Piece ****************************** 246 if (options.collection !== false) { 247 var testElem = document.createElement('canvas'); 248 if (!!(testElem.getContext && testElem.getContext('2d'))) { 249 var canvasCollection = [], 250 elements = $(options.collection), 251 collectionHeight = options.collectionHeight; 252 253 for (var i = 0; i < elements.length; i++) { 254 var bounds = elements[i].getBoundingClientRect(), 255 canvas = document.createElement('canvas'),
256 collisionData = []; 257 258 if (bounds.top - collectionHeight > 0) { 259 document.body.appendChild(canvas); 260 canvas.style.position = 'absolute'; 261 canvas.height = collectionHeight; 262 canvas.width = bounds.width; 263 canvas.style.left = bounds.left + 'px'; 264 canvas.style.top = bounds.top - collectionHeight + 'px'; 265 266 for (var w = 0; w < bounds.width; w++) { 267 collisionData[w] = []; 268 } 269 270 canvasCollection.push({ element: canvas, x: bounds.left, y: bounds.top - collectionHeight, width: bounds.width, height: collectionHeight, colData: collisionData }); 271 } 272 } 273 } else { 274 // Canvas element isnt supported 275 options.collection = false; 276 } 277 } 278 // ************************************************ 279 280 // This will reduce the horizontal scroll bar from displaying, when the effect is applied to the whole page 281 if ($(element).get(0).tagName === $(document).get(0).tagName) { 282 widthOffset = 25; 283 } 284 285 // Bind the window resize event so we can get the innerHeight again 286 $(window).bind("resize", function () { 287 elHeight = $(element)[0].clientHeight; 288 elWidth = $(element)[0].offsetWidth; 289 console.log(elHeight); 290 }); 291 292 293 // initialize the flakes 294 for (i = 0; i < options.flakeCount; i += 1) { 295 flakeId = flakes.length; 296 flakes.push(new Flake(random(widthOffset, elWidth - widthOffset), random(0, elHeight), random((options.minSize * 100), (options.maxSize * 100)) / 100, random(options.minSpeed, options.maxSpeed), flakeId)); 297 } 298 299 // This adds the style to make the snowflakes round via border radius property 300 if (options.round) { 301 $('.snowfall-flakes').css({ '-moz-border-radius': options.maxSize, '-webkit-border-radius': options.maxSize, 'border-radius': options.maxSize }); 302 } 303 304 // This adds shadows just below the snowflake so they pop a bit on lighter colored web pages 305 if (options.shadow) { 306 $('.snowfall-flakes').css({ '-moz-box-shadow': '1px 1px 1px #555', '-webkit-box-shadow': '1px 1px 1px #555', 'box-shadow': '1px 1px 1px #555' }); 307 } 308 309 // On newer Macbooks Snowflakes will fall based on deviceorientation 310 var doRatio = false; 311 if (options.deviceorientation) { 312 $(window).bind('deviceorientation', function (event) { 313 doRatio = event.originalEvent.gamma * 0.1; 314 }); 315 } 316 317 // this controls flow of the updating snow 318 function snow() { 319 for (i = 0; i < flakes.length; i += 1) { 320 flakes[i].update(); 321 } 322 323 snowTimeout = requestAnimationFrame(function () { snow() }); 324 } 325 326 snow(); 327 328 // clears the snowflakes 329 this.clear = function () { 330 $(element).children('.snowfall-flakes').remove(); 331 flakes = []; 332 cancelAnimationFrame(snowTimeout); 333 } 334 }; 335 336 // Initialize the options and the plugin 337 $.fn.snowfall = function (options) { 338 if (typeof (options) == "object" || options == undefined) { 339 return this.each(function (i) { 340 (new $.snowfall(this, options)); 341 }); 342 } else if (typeof (options) == "string") { 343 return this.each(function (i) { 344 var snow = $(this).data('snowfall'); 345 if (snow) { 346 snow.clear(); 347 } 348 }); 349 } 350 }; 351})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.