UNPKG

clickspark.js

Version:

ClickSpark.js is a javascript utility that adds beautiful particle effects to your javascript events. Add image-files as single particles and configure where and when a particle fountain should be fired.

415 lines (360 loc) 13.8 kB
/* * ClickSpark.js * https://github.com/ymc-thzi/clickspark.js * * Thomas Zinnbauer @ YMC * * 2015 YMC AG | Sonnenstrasse 4 | CH-8280 Kreuzlingen | Switzerland * http://www.ymc.ch * */ var clickSpark = (function(){ "use strict"; var $ = jQuery; //global default spec var csDefaultSpecs = { particleImagePath: '', particleCount: 35, particleSpeed: 12, particleDuration: 400, particleSize: 12, particleRotationSpeed: 0, animationType: 'explosion', callback: null } //setup clickSpark as a jQuery function $.fn.clickSpark = function (spec) { spec = $.extend({}, csDefaultSpecs, spec); $(this).on("click", function (e) { //set specification vars clickSpark.setParticleImagePath(spec.particleImagePath); clickSpark.setParticleCount(spec.particleCount); clickSpark.setParticleSpeed(spec.particleSpeed); clickSpark.setParticleDuration(spec.particleDuration); clickSpark.setParticleSize(spec.particleSize); clickSpark.setParticleRotationSpeed(spec.particleRotationSpeed); clickSpark.setAnimationType(spec.animationType); clickSpark.setCallback(spec.callback); //call the on click fireParticle clickSpark.stdFuncOCl(e); }); }; var clickSpark = function (spec) { //spec Attributes var particleImagePath = csDefaultSpecs.particleImagePath; var particleCount = csDefaultSpecs.particleCount; var particleSpeed = csDefaultSpecs.particleSpeed; var particleDuration = csDefaultSpecs.particleDuration; var particleRotationSpeed = csDefaultSpecs.particleRotationSpeed; var animationType = csDefaultSpecs.animationType; var particleSize = csDefaultSpecs.particleSize; var callback = csDefaultSpecs.callback; //private var fps = 60; var targetFrameDuration = 1000 / fps; var currentTime = 0; var running = false; var canvas; var context; var particles = []; var posX; var posY; var DEFAULT_IMG = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAc5pVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyI+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+QWRvYmUgRmlyZXdvcmtzIENTNTwveG1wOkNyZWF0b3JUb29sPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KaBqfRAAAATZJREFUOBGtlM2NwjAQhd+MAndaSAu5cuBAC9RAAyuxVICQtgFqoAUOHLi6BbfAnY3ineeNTXYvKA6WRv59X8bxzAj+teUhLCqgeSg2CGhsuzZbmN3NPARu3uHcAu62F67lJnlkg+VXaAKwC20GEEJLjeJoUsGb+Hj7EJc2M2x1COtWsOuAddp81StwqQKO171ceDbC6FHX4mRzXmtsc1phSw+F/yjMcLKrbcZS0nm78lm+sTUomv4fpb3RPfXkaHy13xcbDRkIanK0f/7BeuHQwsgeJIdBISXKGD41YcM4mgQk7E8UT6DdCfNvANIhr8y1Cd48pcZRJi2pz9WikSdHmf1M2iJEL6KeHGUZYfbbeul1XawexuEDgEk6D/i0Scz+/oMvO56nLpWhXIKofFs9S25MqbQ/ard2fSmw8JoAAAAASUVORK5CYII='; var BASE_PARTICLE_SIZE = 20; //call the constructor constructor(); /* * constructor */ function constructor() { prepareDOMElements(); } /* * setters */ function setParticleImagePath(val) { if (val !== undefined) { particleImagePath = val; } } function setParticleCount(val) { if (val !== undefined) { particleCount = val; } } function setParticleSpeed(val) { if (val !== undefined) { particleSpeed = val; } } function setParticleDuration(val) { if (val !== undefined) { particleDuration = val; } } function setParticleSize(val) { if (val !== undefined) { particleSize = val; } } function setParticleRotationSpeed(val) { if (val !== undefined) { particleRotationSpeed = val; } } function setAnimationType(val) { if (val !== undefined) { animationType = val; } } function setCallback(val) { if (val !== undefined) { callback = val; } } var $body, $document, $window; var $csCanvasContainer, $csParticleCanvas; /* * prepareDOMElements */ function prepareDOMElements() { $(document).ready(function () { $body = $('body'); $document = $(document); $window = $(window); $csParticleCanvas = $('<canvas id="cs-particle-canvas"></canvas>'); $csCanvasContainer = $('<div class="cs-canvas-container"></div>'); $csCanvasContainer.append($csParticleCanvas); $body.prepend( $csCanvasContainer ); //hide CanvasContainer $csCanvasContainer.hide(); //hide canvas $csParticleCanvas.hide(); //set canvas attributes $csCanvasContainer.css({ position: 'absolute', zIndex: 99999, width: '100%', height: '100%', top: window.pageYOffset, left: window.pageXOffset }); }); } /* * createParticle */ function createParticle() { var particle = {}; if (canvas) { particle.x = posX; particle.y = posY; particle.rotation = 0; } particle.speed = rnd(0, particleSpeed); particle.angle = rnd(0, 360) * (Math.PI / 180);//convert to radians; particle.rotationSpeed = rnd((-1) * particleRotationSpeed, particleRotationSpeed); particle.size = particleSize; return particle; } /* * initParticle */ var particleImg; function initParticle() { canvas = $csParticleCanvas[0]; particleImg = new Image(); particleImg.src = particleImagePath || DEFAULT_IMG; if (canvas && typeof(canvas['getContext']) === 'function') { context = canvas.getContext("2d"); context.canvas.width = document.body.clientWidth; context.canvas.height = document.body.clientHeight; } generateParticles(); } /* * generateParticles */ function generateParticles() { for (var i = 0; i < particleCount; i++) { particles.push(createParticle()); } } var animations = { explosion: function (particle) { particle.x += particle.speed * Math.cos(particle.angle); particle.y += particle.speed * Math.sin(particle.angle); }, splash: function (particle) { particle.x -= Math.tan(particle.angle); particle.y += particle.speed * -2; }, falloff: function (particle) { particle.x -= Math.tan(particle.angle); particle.y -= particle.speed * -2; }, blowright: function (particle) { particle.x -= particle.speed * -2; particle.y -= Math.tan(particle.angle / 8); }, blowleft: function (particle) { particle.x += particle.speed * -2; particle.y -= Math.tan(particle.angle / 8); } }; /* * createParticles */ function createParticles() { context.clearRect(0, 0, window.innerWidth, window.innerHeight); var selectedAnimation = animations[animationType] || animations[DEFAULT_ANIMATION]; particles.forEach( function(particle) { selectedAnimation(particle); drawParticles(particle); } ); } /* * drawParticles */ function drawParticles(particle) { particle.size *= 0.96 + (rnd(1, 10) / 100); particle.rotation += particle.rotationSpeed; context.save(); context.translate(particle.x, particle.y); context.rotate(particle.rotation * Math.PI / 180); //fixed base particle size particleImg.width = BASE_PARTICLE_SIZE; particleImg.height = BASE_PARTICLE_SIZE; context.drawImage(particleImg, -(particleImg.width / 2), -(particleImg.height / 2), particle.size, particle.size); context.restore(); } /* * requestAnimationFrame */ window.requestAnimationFrame = (function () { return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback, lastFrameDuration) { var delay = targetFrameDuration; if (lastFrameDuration > delay) { delay -= (lastFrameDuration - delay); if (delay < 0) delay = 0; } window.setTimeout(callback, delay); }; })(); /* * animate */ function animate() { if (running) { var lastTime = currentTime; currentTime = Date.now(); requestAnimationFrame(animate, (currentTime - lastTime)); createParticles(); } } /* * rnd */ function rnd(min, max) { return ((Math.random() * (max - min)) + min); } /* * fireParticles */ function fireParticles(e) { currentTime = Date.now(); //Set the anchor of the particle origin //if click take event coordinates if (e.type === 'click') { posX = e.pageX - window.pageXOffset; posY = e.pageY - window.pageYOffset; } else { //if html-element take position coordinates posX = (e.offset().left + e.width() / 2) - window.pageXOffset; posY = (e.offset().top + e.height() / 2) - window.pageYOffset; } particles = []; initParticle(); //avoid flickering scrollbars on canvas display if ($document.height() > $window.height()) { $body.css('overflow-y', 'inherit'); } else { $body.css('overflow-y', 'hidden'); } if ($document.width() > $window.width()) { $body.css('overflow-x', 'inherit'); } else { $body.css('overflow-x', 'hidden'); } $csCanvasContainer.css({ 'top': window.pageYOffset, 'left': window.pageXOffset }); $csParticleCanvas.css({ 'top': 0, 'left': 0 }); $csCanvasContainer.show(); $csParticleCanvas.show(); window.setTimeout(function () { $csParticleCanvas.fadeOut(fadeCompleted); }, particleDuration); running = true; animate(); function fadeCompleted () { $csParticleCanvas.hide(); $csCanvasContainer.hide(); $body.css({'overflow': 'inherit'}); running = false; if(typeof callback === 'function') { callback.call(this); } } } /* * public methods */ return { setParticleImagePath: function (val) { setParticleImagePath(val); }, setParticleCount: function (val) { setParticleCount(val); }, setParticleSpeed: function (val) { setParticleSpeed(val); }, setParticleDuration: function (val) { setParticleDuration(val); }, setParticleSize: function (val) { setParticleSize(val); }, setParticleRotationSpeed: function (val) { setParticleRotationSpeed(val); }, setAnimationType: function (val) { setAnimationType(val); }, setCallback: function (val) { setCallback(val); }, init: function (spec) { fireParticles(element); }, fireParticles: function (element) { fireParticles(element); }, stdFuncOCl: function (e) { fireParticles(e); } }; }(); return clickSpark; }());