/* * Query UI plugin for raindrops on water effect. * https://github.com/d-harel/raindrops.git */ $.widget("water.raindrops", { options: { waveLength: 340, // Wave Length. A numeric value. The higher the number, the smaller the wave length. canvasWidth: 0, // Width of the water. Default is 100% of the parent's width canvasHeight: 0, // Height of the water. Default is 50% of the parent's height color: '#00aeef', // Water Color frequency: 3, // Raindrops frequency. Higher number means more frequent raindrops. waveHeight: 100 , // Wave height. Higher number means higher waves created by raindrops. density: 0.02, // Water density. Higher number means shorter ripples. rippleSpeed: 0.1, // Speed of the ripple effect. Higher number means faster ripples. rightPadding: 20, // To cover unwanted gaps created by the animation. position:'absolute', positionBottom:0, positionLeft:0 }, _create: function () { var canvas = window.document.createElement('canvas'); if (!this.options.canvasHeight) { this.options.canvasHeight = this.element.height() / 2; } if (!this.options.canvasWidth) { this.options.canvasWidth = this.element.width(); } this.options.realWidth = this.options.canvasWidth + this.options.rightPadding; canvas.height = this.options.canvasHeight; canvas.width = this.options.realWidth; canvas.setAttribute("id", "raincanvas"); this.ctx = canvas.getContext('2d'); this.ctx.fillStyle = this.options.color; this.element.append(canvas); canvas.parentElement.style.overflow = 'hidden'; canvas.parentElement.style.position = 'relative'; canvas.style.position = this.options.position; canvas.style.bottom = this.options.positionBottom; canvas.style.left = this.options.positionLeft; this.springs = []; for (var i = 0; i < this.options.waveLength; i++) { this.springs[i] = new this.Spring(); } raindropsAnimationTick(this); }, Spring: function () { this.p = 0; this.v = 0; //this.update = function (damp, tens) this.update = function (density, rippleSpeed) { //this.v += (-tens * this.p - damp * this.v); this.v += (-rippleSpeed * this.p - density * this.v); this.p += this.v; }; }, updateSprings: function (spread) { var i; for (i = 0; i < this.options.waveLength; i++) { //this.springs[i].update(0.02, 0.1); this.springs[i].update(this.options.density, this.options.rippleSpeed); } var leftDeltas = [], rightDeltas = []; for (var t = 0; t < 8; t++) { for (i = 0; i < this.options.waveLength; i++) { if (i > 0) { leftDeltas[i] = spread * (this.springs[i].p - this.springs[i - 1].p); this.springs[i - 1].v += leftDeltas[i]; } if (i < this.options.waveLength - 1) { rightDeltas[i] = spread * (this.springs[i].p - this.springs[i + 1].p); this.springs[i + 1].v += rightDeltas[i]; } } for (i = 0; i < this.options.waveLength; i++) { if (i > 0) this.springs[i - 1].p += leftDeltas[i]; if (i < this.options.waveLength - 1) this.springs[i + 1].p += rightDeltas[i]; } } }, renderWaves: function () { var i; this.ctx.beginPath(); this.ctx.moveTo(0, this.options.canvasHeight); for (i = 0; i < this.options.waveLength; i++) { this.ctx.lineTo(i * (this.options.realWidth / this.options.waveLength), (this.options.canvasHeight / 2) + this.springs[i].p); } this.ctx.lineTo(this.options.realWidth, this.options.canvasHeight); this.ctx.fill(); } }); function raindropsAnimationTick(drop) { if ((Math.random() * 100) < drop.options.frequency) drop.springs[Math.floor(Math.random() * drop.options.waveLength)].p = drop.options.waveHeight; drop.ctx.clearRect(0, 0, drop.options.realWidth, drop.options.canvasHeight); drop.updateSprings(0.1); drop.renderWaves(); requestAnimationFrame(function () { raindropsAnimationTick(drop); }); } ;