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// requestAnimationFrame polyfill from https://github.com/darius/requestAnimationFrame 71if (!Date.now) 72 Date.now = function() { return new Date().getTime(); }; 73 74(function() { 75 'use strict'; 76 77 var vendors = ['webkit', 'moz']; 78 for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) { 79 var vp = vendors[i]; 80 window.requestAnimationFrame = window[vp+'RequestAnimationFrame']; 81 window.cancelAnimationFrame = (window[vp+'CancelAnimationFrame'] 82 || window[vp+'CancelRequestAnimationFrame']); 83 } 84 if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) // iOS6 is buggy 85 || !window.requestAnimationFrame || !window.cancelAnimationFrame) { 86 var lastTime = 0; 87 window.requestAnimationFrame = function(callback) { 88 var now = Date.now(); 89 var nextTime = Math.max(lastTime + 16, now); 90 return setTimeout(function() { callback(lastTime = nextTime); }, 91 nextTime - now); 92 }; 93 window.cancelAnimationFrame = clearTimeout; 94 } 95}()); 96 97(function($){ 98 $.snowfall = function(element, options){ 99 var flakes = [], 100 defaults = { 101 flakeCount : 35, 102 flakeColor : '#ffffff', 103 flakePosition: 'absolute', 104 flakeIndex: 999999, 105 minSize : 1, 106 maxSize : 2, 107 minSpeed : 1, 108 maxSpeed : 5, 109 round : false, 110 shadow : false, 111 collection : false, 112 collectionHeight : 40, 113 deviceorientation : false 114 }, 115 options = $.extend(defaults, options), 116 random = function random(min, max){ 117 return Math.round(min + Math.random()*(max-min)); 118 }; 119 120 $(element).data("snowfall", this); 121 122 // Snow flake object 123 function Flake(_x, _y, _size, _speed){ 124 // Flake properties 125 this.x = _x; 126 this.y = _y; 127 this.size = _size; 128 this.speed = _speed; 129 this.step = 0; 130 this.stepSize = random(1,10) / 100; 131 132 if(options.collection){ 133 this.target = canvasCollection[random(0,canvasCollection.length-1)]; 134 } 135 136 var flakeMarkup = null; 137 138 if(options.image){ 139 flakeMarkup = document.createElement("img"); 140 flakeMarkup.src = options.image; 141 $(flakeMarkup).attr({ 142 'class': 'snowfall-flakes', 143 }).css({ 144 'width' : this.size, 145 'height' : this.size, 146 'position' : options.flakePosition, 147 'top' : this.y, 148 'left' : this.x, 149 /* 'fontSize' : 0,*/ 150 'zIndex' : options.flakeIndex 151 }); 152 }else{ 153 flakeMarkup = document.createElement("div"); 154 /*$(flakeMarkup).css({'background' : options.flakeColor});*/ 155 $(flakeMarkup).attr({ 156 'class': 'snowfall-flakes', 157 }).css({ 158 'width' : this.size, 159 'height' : this.size, 160 'position' : options.flakePosition, 161 'top' : this.y, 162 'left' : this.x, 163 /* 'fontSize' : 0,*/ 164 'zIndex' : options.flakeIndex 165 }); 166 } 167 168 169 170 if($(element).get(0).tagName === $(document).get(0).tagName){ 171 $('body').append($(flakeMarkup)); 172 element = $('body'); 173 }else{ 174 $(element).append($(flakeMarkup)); 175 } 176 177 this.element = flakeMarkup; 178 179 // Update function, used to update the snow flakes, and checks current snowflake against bounds 180 this.update = function(){ 181 this.y += this.speed; 182 183 if(this.y > (elHeight) - (this.size + 6)){ 184 this.reset(); 185 } 186 187 this.element.style.top = this.y + 'px'; 188 this.element.style.left = this.x + 'px'; 189 190 this.step += this.stepSize; 191 192 if (doRatio === false) { 193 this.x += Math.cos(this.step); 194 } else {
195 this.x += (doRatio + Math.cos(this.step)); 196 } 197 198 // Pileup check 199 if(options.collection){ 200 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){ 201 var ctx = this.target.element.getContext("2d"), 202 curX = this.x - this.target.x, 203 curY = this.y - this.target.y, 204 colData = this.target.colData; 205 206 if(colData[parseInt(curX)][parseInt(curY+this.speed+this.size)] !== undefined || curY+this.speed+this.size > this.target.height){ 207 if(curY+this.speed+this.size > this.target.height){ 208 while(curY+this.speed+this.size > this.target.height && this.speed > 0){ 209 this.speed *= .5; 210 } 211 212 ctx.fillStyle = defaults.flakeColor; 213 214 if(colData[parseInt(curX)][parseInt(curY+this.speed+this.size)] == undefined){ 215 colData[parseInt(curX)][parseInt(curY+this.speed+this.size)] = 1; 216 ctx.fillRect(curX, (curY)+this.speed+this.size, this.size, this.size); 217 }else{ 218 colData[parseInt(curX)][parseInt(curY+this.speed)] = 1; 219 ctx.fillRect(curX, curY+this.speed, this.size, this.size); 220 } 221 this.reset(); 222 }else{ 223 // flow to the sides 224 this.speed = 1; 225 this.stepSize = 0; 226 227 if(parseInt(curX)+1 < this.target.width && colData[parseInt(curX)+1][parseInt(curY)+1] == undefined ){ 228 // go left 229 this.x++; 230 }else if(parseInt(curX)-1 > 0 && colData[parseInt(curX)-1][parseInt(curY)+1] == undefined ){ 231 // go right 232 this.x--; 233 }else{ 234 //stop 235 ctx.fillStyle = defaults.flakeColor; 236 ctx.fillRect(curX, curY, this.size, this.size); 237 colData[parseInt(curX)][parseInt(curY)] = 1; 238 this.reset(); 239 } 240 } 241 } 242 } 243 } 244 245 if(this.x + this.size > (elWidth) - widthOffset || this.x < widthOffset){ 246 this.reset(); 247 } 248 } 249 250 // Resets the snowflake once it reaches one of the bounds set 251 this.reset = function(){ 252 this.y = 0; 253 this.x = random(widthOffset, elWidth - widthOffset); 254 this.stepSize = random(1,10) / 100; 255 this.size = random((options.minSize * 100), (options.maxSize * 100)) / 100; 256 this.element.style.width = this.size + 'px'; 257 this.element.style.height = this.size + 'px'; 258 this.speed = random(options.minSpeed, options.maxSpeed); 259 } 260 } 261 262 // local vars 263 var i = 0, 264 elHeight = $(element).height(), 265 elWidth = $(element).width(), 266 widthOffset = 0, 267 snowTimeout = 0; 268 269 // Collection Piece ****************************** 270 if(options.collection !== false){ 271 var testElem = document.createElement('canvas'); 272 if(!!(testElem.getContext && testElem.getContext('2d'))){ 273 var canvasCollection = [], 274 elements = $(options.collection), 275 collectionHeight = options.collectionHeight; 276 277 for(var i =0; i < elements.length; i++){ 278 var bounds = elements[i].getBoundingClientRect(), 279 $canvas = $('<canvas/>', 280 { 281 'class' : 'snowfall-canvas' 282 }), 283 collisionData = []; 284 285 if(bounds.top-collectionHeight > 0){ 286 $('body').append($canvas); 287 288 $canvas.css({ 289 'position' : options.flakePosition, 290 'left' : bounds.left + 'px', 291 'top' : bounds.top-collectionHeight + 'px' 292 }) 293 .prop({ 294 width: bounds.width, 295 height: collectionHeight 296 }); 297 298 for(var w = 0; w < bounds.width; w++){ 299 collisionData[w] = []; 300 } 301 302 canvasCollection.push({ 303 element : $canvas.get(0), 304 x : bounds.left, 305 y : bounds.top-collectionHeight, 306 width : bounds.width, 307 height: collectionHeight, 308 colData : collisionData 309 }); 310 } 311 } 312 }else{ 313 // Canvas element isnt supported 314 options.collection = false;
315 } 316 } 317 // ************************************************ 318 319 // This will reduce the horizontal scroll bar from displaying, when the effect is applied to the whole page 320 if($(element).get(0).tagName === $(document).get(0).tagName){ 321 widthOffset = 25; 322 } 323 324 // Bind the window resize event so we can get the innerHeight again 325 $(window).bind("resize", function(){ 326 elHeight = $(element)[0].clientHeight; 327 elWidth = $(element)[0].offsetWidth; 328 }); 329 330 331 // initialize the flakes 332 for(i = 0; i < options.flakeCount; i+=1){ 333 flakes.push(new Flake(random(widthOffset,elWidth - widthOffset), random(0, elHeight), random((options.minSize * 100), (options.maxSize * 100)) / 100, random(options.minSpeed, options.maxSpeed))); 334 } 335 336 // This adds the style to make the snowflakes round via border radius property 337 if(options.round){ 338 $('.snowfall-flakes').css({'-moz-border-radius' : options.maxSize, '-webkit-border-radius' : options.maxSize, 'border-radius' : options.maxSize}); 339 } 340 341 if(options.customsymbol){ 342 $('.snowfall-flakes').html(options.customsymbol); 343 } 344 345 // This adds shadows just below the snowflake so they pop a bit on lighter colored web pages 346 if(options.shadow){ 347 $('.snowfall-flakes').css({'-moz-box-shadow' : '1px 1px 1px #555', '-webkit-box-shadow' : '1px 1px 1px #555', 'box-shadow' : '1px 1px 1px #555'}); 348 } 349 350 // On newer Macbooks Snowflakes will fall based on deviceorientation 351 var doRatio = false; 352 if (options.deviceorientation) { 353 $(window).bind('deviceorientation', function(event) { 354 doRatio = event.originalEvent.gamma * 0.1; 355 }); 356 } 357 358 // this controls flow of the updating snow 359 function snow(){ 360 for( i = 0; i < flakes.length; i += 1){ 361 flakes[i].update(); 362 } 363 364 snowTimeout = requestAnimationFrame(function(){snow()}); 365 } 366 367 snow(); 368 369 // clears the snowflakes 370 this.clear = function(){ 371 $('.snowfall-canvas').remove(); 372 $(element).children('.snowfall-flakes').remove(); 373 cancelAnimationFrame(snowTimeout); 374 } 375 }; 376 377 // Initialize the options and the plugin 378 $.fn.snowfall = function(options){ 379 if(typeof(options) == "object" || options == undefined){ 380 return this.each(function(i){ 381 (new $.snowfall(this, options)); 382 }); 383 }else if (typeof(options) == "string") { 384 return this.each(function(i){ 385 var snow = $(this).data('snowfall'); 386 if(snow){ 387 snow.clear(); 388 } 389 }); 390 } 391 }; 392})(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.