diff --git a/daisy.js b/daisy.js new file mode 100644 index 0000000..7bb1a10 --- /dev/null +++ b/daisy.js @@ -0,0 +1,462 @@ +/*! + * daisyjs - https://github.com/WarenGonzaga/daisy.js#readme + * Version: 1.0.0 + * Demo: https://daisyjs.warengonzaga.com/ + * Licensed under the MIT license - http://opensource.org/licenses/MIT + * Copyright (c) 2020 Waren Gonzaga + * + * Facebook: @WarenGonzagaOfficialPage + * Twitter: @Waren_Gonzaga + * Github: @WarenGonzaga + * Website: warengonzaga.com + * + * Maintained and LTS Version of Particleground by jnicol + * https://github.com/jnicol/particleground + * + * Donote or Support! + * https://buymeacoff.ee/warengonzaga + */ + +;(function(window, document) { + "use strict"; + var pluginName = 'daisyjs'; + + // http://youmightnotneedjquery.com/#deep_extend + function extend(out) { + out = out || {}; + for (var i = 1; i < arguments.length; i++) { + var obj = arguments[i]; + if (!obj) continue; + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + if (typeof obj[key] === 'object') + deepExtend(out[key], obj[key]); + else + out[key] = obj[key]; + } + } + } + return out; + } + + var $ = window.jQuery; + + function Plugin(element, options) { + var canvasSupport = !!document.createElement('canvas').getContext; + var canvas; + var ctx; + var particles = []; + var raf; + var mouseX = 0; + var mouseY = 0; + var winW; + var winH; + var desktop = !navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry|BB10|mobi|tablet|opera mini|nexus 7)/i); + var orientationSupport = !!window.DeviceOrientationEvent; + var tiltX = 0; + var pointerX; + var pointerY; + var tiltY = 0; + var paused = false; + + options = extend({}, window[pluginName].defaults, options); + + /** + * Init + */ + function init() { + if (!canvasSupport) { return; } + + // create canvas + canvas = document.createElement('canvas'); + canvas.className = 'pg-canvas'; + canvas.style.display = 'block'; + element.insertBefore(canvas, element.firstChild); + ctx = canvas.getContext('2d'); + styleCanvas(); + + // create particles + var numParticles = Math.round((canvas.width * canvas.height) / options.density); + for (var i = 0; i < numParticles; i++) { + var p = new Particle(); + p.setStackPos(i); + particles.push(p); + } + + window.addEventListener('resize', function() { + resizeHandler(); + }, false); + + document.addEventListener('mousemove', function(e) { + mouseX = e.pageX; + mouseY = e.pageY; + }, false); + + if (orientationSupport && !desktop) { + window.addEventListener('deviceorientation', function () { + // contrain tilt range to [-30,30] + tiltY = Math.min(Math.max(-event.beta, -30), 30); + tiltX = Math.min(Math.max(-event.gamma, -30), 30); + }, true); + } + + draw(); + hook('onInit'); + } + + /** + * Style the canvas + */ + function styleCanvas() { + canvas.width = element.offsetWidth; + canvas.height = element.offsetHeight; + ctx.fillStyle = options.dotColor; + ctx.strokeStyle = options.lineColor; + ctx.lineWidth = options.lineWidth; + } + + /** + * Draw particles + */ + function draw() { + if (!canvasSupport) { return; } + + winW = window.innerWidth; + winH = window.innerHeight; + + // wipe canvas + ctx.clearRect(0, 0, canvas.width, canvas.height); + + // update particle positions + for (var i = 0; i < particles.length; i++) { + particles[i].updatePosition(); + } + // draw particles + for (i = 0; i < particles.length; i++) { + particles[i].draw(); + } + + // call this function next time screen is redrawn + if (!paused) { + raf = requestAnimationFrame(draw); + } + } + + /** + * Add/remove particles. + */ + function resizeHandler() { + // resize the canvas + styleCanvas(); + + var elWidth = element.offsetWidth; + var elHeight = element.offsetHeight; + + // remove particles that are outside the canvas + for (var i = particles.length - 1; i >= 0; i--) { + if (particles[i].position.x > elWidth || particles[i].position.y > elHeight) { + particles.splice(i, 1); + } + } + + // adjust particle density + var numParticles = Math.round((canvas.width * canvas.height) / options.density); + if (numParticles > particles.length) { + while (numParticles > particles.length) { + var p = new Particle(); + particles.push(p); + } + } else if (numParticles < particles.length) { + particles.splice(numParticles); + } + + // re-index particles + for (i = particles.length - 1; i >= 0; i--) { + particles[i].setStackPos(i); + } + } + + /** + * Pause particle system + */ + function pause() { + paused = true; + } + + /** + * Start particle system + */ + function start() { + paused = false; + draw(); + } + + /** + * Particle + */ + + function Particle() { + this.stackPos = this.stackPos; + this.active = true; + this.layer = Math.ceil(Math.random() * 3); + this.parallaxOffsetX = 0; + this.parallaxOffsetY = 0; + // initial particle position + this.position = { + x: Math.ceil(Math.random() * canvas.width), + y: Math.ceil(Math.random() * canvas.height) + }; + // random particle speed, within min and max values + this.speed = {}; + switch (options.directionX) { + case 'left': + this.speed.x = +(-options.maxSpeedX + (Math.random() * options.maxSpeedX) - options.minSpeedX).toFixed(2); + break; + case 'right': + this.speed.x = +((Math.random() * options.maxSpeedX) + options.minSpeedX).toFixed(2); + break; + default: + this.speed.x = +((-options.maxSpeedX / 2) + (Math.random() * options.maxSpeedX)).toFixed(2); + this.speed.x += this.speed.x > 0 ? options.minSpeedX : -options.minSpeedX; + break; + } + switch (options.directionY) { + case 'up': + this.speed.y = +(-options.maxSpeedY + (Math.random() * options.maxSpeedY) - options.minSpeedY).toFixed(2); + break; + case 'down': + this.speed.y = +((Math.random() * options.maxSpeedY) + options.minSpeedY).toFixed(2); + break; + default: + this.speed.y = +((-options.maxSpeedY / 2) + (Math.random() * options.maxSpeedY)).toFixed(2); + this.speed.x += this.speed.y > 0 ? options.minSpeedY : -options.minSpeedY; + break; + } + } + + /** + * Draw particle + */ + Particle.prototype.draw = function() { + // draw circle + ctx.beginPath(); + ctx.arc(this.position.x + this.parallaxOffsetX, this.position.y + this.parallaxOffsetY, options.particleRadius / 2, 0, Math.PI * 2, true); + ctx.closePath(); + ctx.fill(); + + // draw lines + ctx.beginPath(); + // iterate over all particles which are higher in the stack than this one + for (var i = particles.length - 1; i > this.stackPos; i--) { + var p2 = particles[i]; + + // pythagorus theorum to get distance between two points + var a = this.position.x - p2.position.x; + var b = this.position.y - p2.position.y; + var dist = Math.sqrt((a * a) + (b * b)).toFixed(2); + + // if the two particles are in proximity, join them + if (dist < options.proximity) { + ctx.moveTo(this.position.x + this.parallaxOffsetX, this.position.y + this.parallaxOffsetY); + if (options.curvedLines) { + ctx.quadraticCurveTo(Math.max(p2.position.x, p2.position.x), Math.min(p2.position.y, p2.position.y), p2.position.x + p2.parallaxOffsetX, p2.position.y + p2.parallaxOffsetY); + } else { + ctx.lineTo(p2.position.x + p2.parallaxOffsetX, p2.position.y + p2.parallaxOffsetY); + } + } + } + ctx.stroke(); + ctx.closePath(); + }; + + /** + * Update particle position + */ + Particle.prototype.updatePosition = function() { + if (options.parallax) { + if (orientationSupport && !desktop) { + // map tiltX range [-30,30] to range [0,winW] + var ratioX = (winW - 0) / (30 - (-30)); + pointerX = (tiltX - (-30)) * ratioX + 0; + // map tiltY range [-30,30] to range [0,winH] + var ratioY = (winH - 0) / (30 - (-30)); + pointerY = (tiltY - (-30)) * ratioY + 0; + } else { + pointerX = mouseX; + pointerY = mouseY; + } + // calculate parallax offsets + this.parallaxTargX = (pointerX - (winW / 2)) / (options.parallaxMultiplier * this.layer); + this.parallaxOffsetX += (this.parallaxTargX - this.parallaxOffsetX) / 10; // easing equation + this.parallaxTargY = (pointerY - (winH / 2)) / (options.parallaxMultiplier * this.layer); + this.parallaxOffsetY += (this.parallaxTargY - this.parallaxOffsetY) / 10; // easing equation + } + + var elWidth = element.offsetWidth; + var elHeight = element.offsetHeight; + + switch (options.directionX) { + case 'left': + if (this.position.x + this.speed.x + this.parallaxOffsetX < 0) { + this.position.x = elWidth - this.parallaxOffsetX; + } + break; + case 'right': + if (this.position.x + this.speed.x + this.parallaxOffsetX > elWidth) { + this.position.x = 0 - this.parallaxOffsetX; + } + break; + default: + // if particle has reached edge of canvas, reverse its direction + if (this.position.x + this.speed.x + this.parallaxOffsetX > elWidth || this.position.x + this.speed.x + this.parallaxOffsetX < 0) { + this.speed.x = -this.speed.x; + } + break; + } + + switch (options.directionY) { + case 'up': + if (this.position.y + this.speed.y + this.parallaxOffsetY < 0) { + this.position.y = elHeight - this.parallaxOffsetY; + } + break; + case 'down': + if (this.position.y + this.speed.y + this.parallaxOffsetY > elHeight) { + this.position.y = 0 - this.parallaxOffsetY; + } + break; + default: + // if particle has reached edge of canvas, reverse its direction + if (this.position.y + this.speed.y + this.parallaxOffsetY > elHeight || this.position.y + this.speed.y + this.parallaxOffsetY < 0) { + this.speed.y = -this.speed.y; + } + break; + } + + // move particle + this.position.x += this.speed.x; + this.position.y += this.speed.y; + }; + + /** + * Setter: particle stacking position + */ + Particle.prototype.setStackPos = function(i) { + this.stackPos = i; + }; + + function option (key, val) { + if (val) { + options[key] = val; + } else { + return options[key]; + } + } + + function destroy() { + console.log('destroy'); + canvas.parentNode.removeChild(canvas); + hook('onDestroy'); + if ($) { + $(element).removeData('plugin_' + pluginName); + } + } + + function hook(hookName) { + if (options[hookName] !== undefined) { + options[hookName].call(element); + } + } + + init(); + + return { + option: option, + destroy: destroy, + start: start, + pause: pause + }; + } + + window[pluginName] = function(elem, options) { + return new Plugin(elem, options); + }; + + window[pluginName].defaults = { + minSpeedX: 0.1, + maxSpeedX: 0.7, + minSpeedY: 0.1, + maxSpeedY: 0.7, + directionX: 'center', // 'center', 'left' or 'right'. 'center' = dots bounce off edges + directionY: 'center', // 'center', 'up' or 'down'. 'center' = dots bounce off edges + density: 10000, // how many particles will be generated: one particle every n pixels + dotColor: '#666666', + lineColor: '#666666', + particleRadius: 7, // dot size + lineWidth: 1, + curvedLines: false, + proximity: 100, // how close two dots need to be before they join + parallax: true, + parallaxMultiplier: 5, // the lower the number, the more extreme the parallax effect + onInit: function() {}, + onDestroy: function() {} + }; + + // nothing wrong with hooking into jQuery if it's there... + if ($) { + $.fn[pluginName] = function(options) { + if (typeof arguments[0] === 'string') { + var methodName = arguments[0]; + var args = Array.prototype.slice.call(arguments, 1); + var returnVal; + this.each(function() { + if ($.data(this, 'plugin_' + pluginName) && typeof $.data(this, 'plugin_' + pluginName)[methodName] === 'function') { + returnVal = $.data(this, 'plugin_' + pluginName)[methodName].apply(this, args); + } + }); + if (returnVal !== undefined){ + return returnVal; + } else { + return this; + } + } else if (typeof options === "object" || !options) { + return this.each(function() { + if (!$.data(this, 'plugin_' + pluginName)) { + $.data(this, 'plugin_' + pluginName, new Plugin(this, options)); + } + }); + } + }; + } + +})(window, document); + +/** + * requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel + * @see: http://paulirish.com/2011/requestanimationframe-for-smart-animating/ + * @see: http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating + * @license: MIT license + */ +(function() { + var lastTime = 0; + var vendors = ['ms', 'moz', 'webkit', 'o']; + for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { + window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; + window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame']; + } + + if (!window.requestAnimationFrame) + window.requestAnimationFrame = function(callback, element) { + var currTime = new Date().getTime(); + var timeToCall = Math.max(0, 16 - (currTime - lastTime)); + var id = window.setTimeout(function() { callback(currTime + timeToCall); }, + timeToCall); + lastTime = currTime + timeToCall; + return id; + }; + + if (!window.cancelAnimationFrame) + window.cancelAnimationFrame = function(id) { + clearTimeout(id); + }; +}()); diff --git a/daisy.min.js b/daisy.min.js new file mode 100644 index 0000000..0e49314 --- /dev/null +++ b/daisy.min.js @@ -0,0 +1,20 @@ +/*! + * daisyjs - https://github.com/WarenGonzaga/daisy.js#readme + * Version: 1.0.0 + * Demo: https://daisyjs.warengonzaga.com/ + * Licensed under the MIT license - http://opensource.org/licenses/MIT + * Copyright (c) 2020 Waren Gonzaga + * + * Facebook: @WarenGonzagaOfficialPage + * Twitter: @Waren_Gonzaga + * Github: @WarenGonzaga + * Website: warengonzaga.com + * + * Maintained and LTS Version of Particleground by jnicol + * https://github.com/jnicol/particleground + * + * Donote or Support! + * https://buymeacoff.ee/warengonzaga + */ + +!function(Y,O){"use strict";var S="daisyjs";var M=Y.jQuery;function s(n,o){var r,s,e,a,h,p,l=!!O.createElement("canvas").getContext,d=[],f=0,c=0,x=!navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry|BB10|mobi|tablet|opera mini|nexus 7)/i),u=!!Y.DeviceOrientationEvent,m=0,y=0,i=!1;function g(){r.width=n.offsetWidth,r.height=n.offsetHeight,s.fillStyle=o.dotColor,s.strokeStyle=o.lineColor,s.lineWidth=o.lineWidth}function w(){if(l){e=Y.innerWidth,a=Y.innerHeight,s.clearRect(0,0,r.width,r.height);for(var t=0;tthis.stackPos;t--){var i=d[t],e=this.position.x-i.position.x,a=this.position.y-i.position.y;Math.sqrt(e*e+a*a).toFixed(2)t&&(this.position.x=0-this.parallaxOffsetX);break;default:(this.position.x+this.speed.x+this.parallaxOffsetX>t||this.position.x+this.speed.x+this.parallaxOffsetX<0)&&(this.speed.x=-this.speed.x)}switch(o.directionY){case"up":this.position.y+this.speed.y+this.parallaxOffsetY<0&&(this.position.y=i-this.parallaxOffsetY);break;case"down":this.position.y+this.speed.y+this.parallaxOffsetY>i&&(this.position.y=0-this.parallaxOffsetY);break;default:(this.position.y+this.speed.y+this.parallaxOffsetY>i||this.position.y+this.speed.y+this.parallaxOffsetY<0)&&(this.speed.y=-this.speed.y)}this.position.x+=this.speed.x,this.position.y+=this.speed.y},v.prototype.setStackPos=function(t){this.stackPos=t},function(){if(l){(r=O.createElement("canvas")).className="pg-canvas",r.style.display="block",n.insertBefore(r,n.firstChild),s=r.getContext("2d"),g();for(var t=Math.round(r.width*r.height/o.density),i=0;it||d[e].position.y>i)&&d.splice(e,1);var a=Math.round(r.width*r.height/o.density);if(a>d.length)for(;a>d.length;){var s=new v;d.push(s)}else a img { + width: 200px; + height: auto; +} + +h1 { + color: #ff5c5c; + font-size: 100px; + font-family: 'Marcellus SC', serif; + font-weight: 800; +} + +.btn { + top: 30px; + position: relative; + background: #ff5c5c; + color: #fff; + padding: 20px 20px; + text-decoration: none; + text-transform: uppercase; + font-weight: 800; + letter-spacing: 0.1em; + border-radius: 10px; + transition-duration: 0.3s; +} + +.btn:hover { + background: #fff; + color: #ff5c5c; + transition-duration: 0.3s; +} + +span { + top: 70px; + display: block; + position: relative; + color: #fff; + font-weight: 500; +} + +span > a { + color: #fff; +} diff --git a/img/daisy-official-icon.png b/demo/img/daisy-official-icon.png similarity index 100% rename from img/daisy-official-icon.png rename to demo/img/daisy-official-icon.png diff --git a/demo/index.html b/demo/index.html new file mode 100644 index 0000000..ef7e3c3 --- /dev/null +++ b/demo/index.html @@ -0,0 +1,41 @@ + + + + + + + + + DaisyJS Demo + + + + + + + + + + Fork me on GitHub + +
+
+ +

DaisyJS

+ Download Now + </> with <3 by Waren Gonzaga +
+
+ + + + + + + \ No newline at end of file diff --git a/demo/js/index.js b/demo/js/index.js new file mode 100644 index 0000000..b3e97dd --- /dev/null +++ b/demo/js/index.js @@ -0,0 +1,22 @@ +/** + * DaisyJS Demo Script + * by Waren Gonzaga + */ + +// in vanilla javascript + +document.addEventListener('DOMContentLoaded', function () { + daisyjs(document.getElementById('momoland'), { + dotColor: '#000', + lineColor: '#222' + }); +}, false); + +// as jquery plugin + +/* $(document).ready(function() { + $('#momoland').daisyjs({ + dotColor: '#000', + lineColor: '#222' + }); +}); */ diff --git a/package.json b/package.json index 6f88a73..d1ba68e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "daisyjs", "version": "1.0.0", - "description": "A JavaScript plugin for snazzy background particle systems. A maintained version and inspired by Particleground.", + "description": "Web animation javascript plugin for beautiful background particle systems. The Maintained and LTS version of popular Particleground.", "main": "gulpfile.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" diff --git a/src/daisy.js b/src/daisy.js index 227bc50..2cdd84b 100644 --- a/src/daisy.js +++ b/src/daisy.js @@ -175,8 +175,9 @@ /** * Particle */ + function Particle() { - this.stackPos = stackPos; + this.stackPos = this.stackPos; this.active = true; this.layer = Math.ceil(Math.random() * 3); this.parallaxOffsetX = 0; @@ -227,7 +228,7 @@ // draw lines ctx.beginPath(); // iterate over all particles which are higher in the stack than this one - for (var i = particles.length - 1; i > tpos; i--) { + for (var i = particles.length - 1; i > this.stackPos; i--) { var p2 = particles[i]; // pythagorus theorum to get distance between two points @@ -322,7 +323,7 @@ * Setter: particle stacking position */ Particle.prototype.setStackPos = function(i) { - stackPos = i; + this.stackPos = i; }; function option (key, val) {