Particles

Size
9,207 Kb
Views
26,312

How do I make an particles?

Particles from an emitter moving behind some text. FPS counter included to measure performance. Select from two strategies : using fillRect() and setting pixels with get/putImageData(). There is a widget to change the number of particles. I get 60fps using fillrect on 10,000 particles, with putImageData I get 100,000 with 55fps.. What is a particles? How do you make a particles? This script and codes were developed by Sakri Rosenstrom on 13 September 2022, Tuesday.

Particles Previews

Particles - Script Codes HTML Codes

<!DOCTYPE html>
<html >
<head> <meta charset="UTF-8"> <title>Particles</title> <link rel="stylesheet" href="css/style.css">
</head>
<body> <div id="canvasContainer"></div>
<span id="textInputSpan"> Enter your name (max 10 chars) : <input id="textInput" maxlength="10" type="text" width="150" /> <button onclick="changeText()">GO!</button> method: <select id="strategySelect" onchange="changeSettings()" > <option value="drawRect">drawRect()</option> <option value="drawRectColor">drawRect() color</option> <option value="perPixel">perPixel()</option> <option value="perPixelColor">perPixel() color</option> </select> particles : <select id="particlesSelect" onchange="changeSettings()" />
</span> <script src="js/index.js"></script>
</body>
</html>

Particles - Script Codes CSS Codes

html, body{ margin : 0px; width : 100%; height : 100%; overflow: hidden; background-color: #000000; font-family: sans-serif;
}
#canvasContainer{ margin : 0px; width : 100%; height : 100%;
}
#textInputSpan{ position: absolute; color: #FFFFFF; font-family: sans-serif;
}

Particles - Script Codes JS Codes

 /* * Stats.js 1.1 * https://code.google.com/p/mrdoob/wiki/stats_js * */ function Stats() { this.init(); } Stats.prototype = { init: function() { this.frames = 0; this.framesMin = 100; this.framesMax = 0; this.time = new Date().getTime(); this.timePrev = new Date().getTime(); this.container = document.createElement("div"); this.container.style.position = 'absolute'; this.container.style.fontFamily = 'Arial'; this.container.style.fontSize = '10px'; this.container.style.backgroundColor = '#000020'; this.container.style.opacity = '0.9'; this.container.style.width = '80px'; this.container.style.paddingTop = '2px'; this.framesText = document.createElement("div"); this.framesText.style.color = '#00ffff'; this.framesText.style.marginLeft = '3px'; this.framesText.style.marginBottom = '3px'; this.framesText.innerHTML = '<strong>FPS</strong>'; this.container.appendChild(this.framesText); this.canvas = document.createElement("canvas"); this.canvas.width = 74; this.canvas.height = 30; this.canvas.style.display = 'block'; this.canvas.style.marginLeft = '3px'; this.canvas.style.marginBottom = '3px'; this.container.appendChild(this.canvas); this.context = this.canvas.getContext("2d"); this.context.fillStyle = '#101030'; this.context.fillRect(0, 0, this.canvas.width, this.canvas.height ); this.contextImageData = this.context.getImageData(0, 0, this.canvas.width, this.canvas.height); setInterval( bargs( function( _this ) { _this.update(); return false; }, this ), 1000 ); }, getDisplayElement: function() { return this.container; }, tick: function() { this.frames++; }, update: function() { this.time = new Date().getTime(); this.fps = Math.round((this.frames * 1000 ) / (this.time - this.timePrev)); //.toPrecision(2); this.framesMin = Math.min(this.framesMin, this.fps); this.framesMax = Math.max(this.framesMax, this.fps); this.framesText.innerHTML = '<strong>' + this.fps + ' FPS</strong> (' + this.framesMin + '-' + this.framesMax + ')'; this.contextImageData = this.context.getImageData(1, 0, this.canvas.width - 1, 30); this.context.putImageData(this.contextImageData, 0, 0); this.context.fillStyle = '#101030'; this.context.fillRect(this.canvas.width - 1, 0, 1, 30); this.index = ( Math.floor(30 - Math.min(30, (this.fps / 60) * 30)) ); this.context.fillStyle = '#80ffff'; this.context.fillRect(this.canvas.width - 1, this.index, 1, 1); this.context.fillStyle = '#00ffff'; this.context.fillRect(this.canvas.width - 1, this.index + 1, 1, 30 - this.index); this.timePrev = this.time; this.frames = 0; } } // Hack by Spite function bargs( _fn ) { var args = []; for( var n = 1; n < arguments.length; n++ ) args.push( arguments[ n ] ); return function () { return _fn.apply( this, args ); }; } (function (window){ var Sakri = window.Sakri || {}; window.Sakri = window.Sakri || Sakri; Sakri.MathUtil = {}; //return number between 1 and 0 Sakri.MathUtil.normalize = function(value, minimum, maximum){ return (value - minimum) / (maximum - minimum); }; //map normalized number to values Sakri.MathUtil.interpolate = function(normValue, minimum, maximum){ return minimum + (maximum - minimum) * normValue; }; //map a value from one set to another Sakri.MathUtil.map = function(value, min1, max1, min2, max2){ return Sakri.MathUtil.interpolate( Sakri.MathUtil.normalize(value, min1, max1), min2, max2); }; Sakri.MathUtil.hexToRgb = function(hex) { // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; hex = hex.replace(shorthandRegex, function(m, r, g, b) { return r + r + g + g + b + b; }); var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); return result ? { r: parseInt(result[1], 16), g: parseInt(result[2], 16), b: parseInt(result[3], 16) } : null; } Sakri.MathUtil.getRandomNumberInRange = function(min, max){ return min + Math.random() * (max - min); }; Sakri.MathUtil.getRandomIntegerInRange = function(min, max){ return Math.round(Sakri.MathUtil.getRandomNumberInRange(min, max)); }; }(window)); //has a dependency on Sakri.MathUtil (function (window){ var Sakri = window.Sakri || {}; window.Sakri = window.Sakri || Sakri; Sakri.Geom = {}; //================================================== //=====================::POINT::==================== //================================================== Sakri.Geom.Point = function (x,y){ this.x = isNaN(x) ? 0 : x; this.y = isNaN(y) ? 0 : y; }; Sakri.Geom.Point.prototype.clone = function(){ return new Sakri.Geom.Point(this.x,this.y); }; Sakri.Geom.Point.prototype.update = function(x, y){ this.x = isNaN(x) ? this.x : x; this.y = isNaN(y) ? this.y : y; }; //================================================== //===================::RECTANGLE::================== //================================================== Sakri.Geom.Rectangle = function (x, y, width, height){ this.update(x, y, width, height); }; Sakri.Geom.Rectangle.prototype.update = function(x, y, width, height){ this.x = isNaN(x) ? 0 : x; this.y = isNaN(y) ? 0 : y; this.width = isNaN(width) ? 0 : width; this.height = isNaN(height) ? 0 : height; }; Sakri.Geom.Rectangle.prototype.getRight = function(){ return this.x + this.width; }; Sakri.Geom.Rectangle.prototype.getBottom = function(){ return this.y + this.height; }; Sakri.Geom.Rectangle.prototype.getCenter = function(){ return new Sakri.Geom.Point(this.getCenterX(), this.getCenterY()); }; Sakri.Geom.Rectangle.prototype.getCenterX = function(){ return this.x + this.width/2; }; Sakri.Geom.Rectangle.prototype.getCenterY=function(){ return this.y + this.height/2; }; Sakri.Geom.Rectangle.prototype.containsPoint = function(x, y){ return x >= this.x && y >= this.y && x <= this.getRight() && y <= this.getBottom(); }; Sakri.Geom.Rectangle.prototype.clone = function(){ return new Sakri.Geom.Rectangle(this.x, this.y, this.width, this.height); }; Sakri.Geom.Rectangle.prototype.toString = function(){ return "Rectangle{x:"+this.x+" , y:"+this.y+" , width:"+this.width+" , height:"+this.height+"}"; }; }(window)); /** * Created by sakri on 27-1-14. * has a dependecy on Sakri.Geom * has a dependecy on Sakri.BitmapUtil */ (function (window){ var Sakri = window.Sakri || {}; window.Sakri = window.Sakri || Sakri; Sakri.CanvasTextUtil = {}; //returns the biggest font size that best fits into given width Sakri.CanvasTextUtil.getFontSizeForWidth = function(string, fontProps, width, canvas, fillStyle, maxFontSize){ if(!canvas){ var canvas = document.createElement("canvas"); } if(!fillStyle){ fillStyle = "#000000"; } if(isNaN(maxFontSize)){ maxFontSize = 500; } var context = canvas.getContext('2d'); context.font = fontProps.getFontString(); context.textBaseline = "top"; var copy = fontProps.clone(); //console.log("getFontSizeForWidth() 1 : ", copy.fontSize); context.font = copy.getFontString(); var textWidth = context.measureText(string).width; //SOME DISAGREEMENT WHETHER THIS SHOOULD BE WITH && or || if(textWidth < width){ while(context.measureText(string).width < width){ copy.fontSize++; context.font = copy.getFontString(); if(copy.fontSize > maxFontSize){ console.log("getFontSizeForWidth() max fontsize reached"); return null; } } }else if(textWidth > width){ while(context.measureText(string).width > width){ copy.fontSize--; context.font = copy.getFontString(); if(copy.fontSize < 0){ console.log("getFontSizeForWidth() min fontsize reached"); return null; } } } //console.log("getFontSizeForWidth() 2 : ", copy.fontSize); return copy.fontSize; }; //========================================================================================= //==============::CANVAS TEXT PROPERTIES::==================================== //======================================================== Sakri.CanvasTextProperties = function(fontWeight, fontStyle, fontSize, fontFace){ this.setFontWeight(fontWeight); this.setFontStyle(fontStyle); this.setFontSize(fontSize); this.fontFace = fontFace ? fontFace : "sans-serif"; }; Sakri.CanvasTextProperties.NORMAL = "normal"; Sakri.CanvasTextProperties.BOLD = "bold"; Sakri.CanvasTextProperties.BOLDER = "bolder"; Sakri.CanvasTextProperties.LIGHTER = "lighter"; Sakri.CanvasTextProperties.ITALIC = "italic"; Sakri.CanvasTextProperties.OBLIQUE = "oblique"; Sakri.CanvasTextProperties.prototype.setFontWeight = function(fontWeight){ switch (fontWeight){ case Sakri.CanvasTextProperties.NORMAL: case Sakri.CanvasTextProperties.BOLD: case Sakri.CanvasTextProperties.BOLDER: case Sakri.CanvasTextProperties.LIGHTER: this.fontWeight = fontWeight; break; default: this.fontWeight = Sakri.CanvasTextProperties.NORMAL; } }; Sakri.CanvasTextProperties.prototype.setFontStyle = function(fontStyle){ switch (fontStyle){ case Sakri.CanvasTextProperties.NORMAL: case Sakri.CanvasTextProperties.ITALIC: case Sakri.CanvasTextProperties.OBLIQUE: this.fontStyle = fontStyle; break; default: this.fontStyle = Sakri.CanvasTextProperties.NORMAL; } }; Sakri.CanvasTextProperties.prototype.setFontSize = function(fontSize){ if(fontSize && fontSize.indexOf && fontSize.indexOf("px")>-1){ var size = fontSize.split("px")[0]; fontProperites.fontSize = isNaN(size) ? 24 : size;//24 is just an arbitrary number return; } this.fontSize = isNaN(fontSize) ? 24 : fontSize;//24 is just an arbitrary number }; Sakri.CanvasTextProperties.prototype.clone = function(){ return new Sakri.CanvasTextProperties(this.fontWeight, this.fontStyle, this.fontSize, this.fontFace); }; Sakri.CanvasTextProperties.prototype.getFontString = function(){ return this.fontWeight + " " + this.fontStyle + " " + this.fontSize + "px " + this.fontFace; }; }(window)); //=========================::UNIT ANIMATOR::=============================== //animates a number from 0-1 (with optional easing) for a given duration and a framerate //this is used to animate or tweeen visuals which are set up using interpolation (function (window){ window.requestAnimationFrame = window.__requestAnimationFrame || window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || (function () { return function (callback, element) { var lastTime = element.__lastTime; if (lastTime === undefined) { lastTime = 0; } var currTime = Date.now(); var timeToCall = Math.max(1, 33 - (currTime - lastTime)); window.setTimeout(callback, timeToCall); element.__lastTime = currTime + timeToCall; }; })(); var Sakri = window.Sakri || {}; window.Sakri = window.Sakri || Sakri; //constructor, duration and framerate must be in milliseconds Sakri.UnitAnimator = function(duration, canvas, updateCallBack, completeCallBack){ this.easingFunction = Sakri.UnitAnimator.easeLinear;//default this.animating = false; this.canvas = canvas; var scope = this; this.loopFunction = function(){scope.loop();}; this.reset(duration, updateCallBack, completeCallBack); }; //t is "time" this.millisecondsAnimated //b is the "beginning" value //c is "change" or the difference of end-start value //d is this.duration //classic Robert Penner easing functions //http://www.robertpenner.com/easing/ Sakri.UnitAnimator.easeLinear = function(t, b, c, d){ return c * (t / d) + b; }; //SINE Sakri.UnitAnimator.easeInSine = function (t, b, c, d){ return -c * Math.cos(t/d * Sakri.MathUtil.HALF_PI) + c + b; }; Sakri.UnitAnimator.easeOutSine = function (t, b, c, d){ return c * Math.sin(t/d * Sakri.MathUtil.HALF_PI) + b; }; Sakri.UnitAnimator.easeInOutSine = function (t, b, c, d){ return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; }; //BOUNCE Sakri.UnitAnimator.easeInBounce = function(t, b, c, d){ return c - Sakri.UnitAnimator.easeOutBounce (d-t, 0, c, d) + b; }; Sakri.UnitAnimator.easeOutBounce = function(t, b, c, d){ if ((t/=d) < (1/2.75)) { return c*(7.5625*t*t) + b; } else if (t < (2/2.75)) { return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; } else if (t < (2.5/2.75)) { return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; } else { return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; } }; Sakri.UnitAnimator.easeInOutBounce = function (t, b, c, d){ if (t < d/2){ return Sakri.UnitAnimator.easeInBounce (t*2, 0, c, d) * .5 + b; } return Sakri.UnitAnimator.easeOutBounce (t*2-d, 0, c, d) * .5 + c*.5 + b; }; //ELASTIC Sakri.UnitAnimator.easeInElastic = function(t, b, c, d, a, p){ var s; if (t==0){ return b; } if ((t/=d)==1){ return b+c; } if (!p){ p=d*.3; } if (!a || a < Math.abs(c)) { a=c; s=p/4; }else{ s = p/Sakri.MathUtil.PI2 * Math.asin (c/a); } return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*Sakri.MathUtil.PI2/p )) + b; }; Sakri.UnitAnimator.easeOutElastic = function(t, b, c, d, a, p){ var s; if (t==0){ return b; } if ((t/=d)==1){ return b+c; } if (!p){ p=d*.3; } if (!a || a < Math.abs(c)) { a=c; s=p/4; }else{ s = p/Sakri.MathUtil.PI2 * Math.asin (c/a); } return (a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*Sakri.MathUtil.PI2/p ) + c + b); }; Sakri.UnitAnimator.easeInOutElastic = function(t, b, c, d, a, p){ var s; if (t==0){ return b; } if ((t/=d/2)==2){ return b+c; } if (!p){ p=d*(.3*1.5); } if (!a || a < Math.abs(c)) { a=c; s=p/4; }else{ s = p/Sakri.MathUtil.PI2 * Math.asin (c/a); } if (t < 1){ return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*Sakri.MathUtil.PI2/p )) + b; } return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*Sakri.MathUtil.PI2/p )*.5 + c + b; }; Sakri.UnitAnimator.easingFunctions = [Sakri.UnitAnimator.easeLinear, Sakri.UnitAnimator.easeInSine, Sakri.UnitAnimator.easeOutSine, Sakri.UnitAnimator.easeInOutSine, Sakri.UnitAnimator.easeInBounce, Sakri.UnitAnimator.easeOutBounce, Sakri.UnitAnimator.easeInOutBounce, Sakri.UnitAnimator.easeInElastic, Sakri.UnitAnimator.easeOutElastic, Sakri.UnitAnimator.easeInOutElastic ]; Sakri.UnitAnimator.getRandomEasingFunction = function(){ return Sakri.UnitAnimator.easingFunctions[Math.floor( Math.random()*Sakri.UnitAnimator.easingFunctions.length )]; }; Sakri.UnitAnimator.prototype.setRandomEasingFunction = function(){ this.easingFunction = Sakri.UnitAnimator.getRandomEasingFunction(); }; Sakri.UnitAnimator.prototype.setEasingFunction = function(easingFunction){ if(Sakri.UnitAnimator.easingFunctions.indexOf(easingFunction) > -1){ this.easingFunction = easingFunction; } }; //easing (t, b, c, d) //@t is the current time (or position) of the tween. This can be seconds or frames, steps, seconds, ms, whatever � as long as the unit is the same as is used for the total time [3]. //@b is the beginning value of the property. //@c is the change between the beginning and destination value of the property. //@d is the total time of the tween. Sakri.UnitAnimator.prototype.getAnimationPercent = function(){ return this.easingFunction(Sakri.MathUtil.normalize(this.millisecondsAnimated, 0, this.duration), 0, 1, 1); }; Sakri.UnitAnimator.prototype.reset = function(duration, updateCallBack, completeCallBack){ this.duration = duration; this.updateCallBack = updateCallBack; this.completeCallBack = completeCallBack; }; Sakri.UnitAnimator.prototype.start = function(easingFunction){ //console.log("Sakri.UnitAnimator.start()"); if(easingFunction){ this.setEasingFunction(easingFunction); } this.animating = true; this.animationStart = Date.now(); this.millisecondsAnimated = 0;//keeps track of how long the animation has been running this.loop(); }; Sakri.UnitAnimator.prototype.loop = function(){ if(!this.animating){ return; } this.update(); window.requestAnimationFrame(this.loopFunction, canvas); } Sakri.UnitAnimator.prototype.pause = function(){ this.animating = false; }; //refactor, make private Sakri.UnitAnimator.prototype.update = function(){ //console.log("Sakri.UnitAnimator.update()",this.getAnimationPercent()); this.millisecondsAnimated = Date.now() - this.animationStart; if(this.millisecondsAnimated >= this.duration){ //console.log("Sakri.UnitAnimator.update() animation complete"); this.pause(); this.millisecondsAnimated = this.duration; this.dispatchUpdate(); this.dispatchComplete(); return; } this.dispatchUpdate(); }; Sakri.UnitAnimator.prototype.dispatchUpdate = function(){ if(this.updateCallBack){ //console.log("Sakri.UnitAnimator.dispatchUpdate()",this.getAnimationPercent()); this.updateCallBack(); } }; Sakri.UnitAnimator.prototype.dispatchComplete = function(){ if(this.completeCallBack){ this.completeCallBack(); } }; }(window)); //============::ACTUAL DEMO::================= window.requestAnimationFrame = window.__requestAnimationFrame || window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || (function () { return function (callback, element) { var lastTime = element.__lastTime; if (lastTime === undefined) { lastTime = 0; } var currTime = Date.now(); var timeToCall = Math.max(1, 33 - (currTime - lastTime)); window.setTimeout(callback, timeToCall); element.__lastTime = currTime + timeToCall; }; })(); var readyStateCheckInterval = setInterval( function() { if (document.readyState === "complete") { clearInterval(readyStateCheckInterval); init(); } }, 10); //======================== //general properties for demo set up //======================== var canvas; var context; var canvasContainer; var htmlBounds; var bounds; var minimumStageWidth = 250; var minimumStageHeight = 250; var maxStageWidth = 1000; var maxStageHeight = 600; var resizeTimeoutId = -1; var stats; function init(){ canvasContainer = document.getElementById("canvasContainer"); window.onresize = resizeHandler; stats = new Stats(); canvasContainer.appendChild( stats.getDisplayElement() ); commitResize(); } function getWidth( element ){return Math.max(element.scrollWidth,element.offsetWidth,element.clientWidth );} function getHeight( element ){return Math.max(element.scrollHeight,element.offsetHeight,element.clientHeight );} //avoid running resize scripts repeatedly if a browser window is being resized by dragging function resizeHandler(){ context.clearRect(0,0,canvas.width, canvas.height); clearTimeout(resizeTimeoutId); clearTimeoutsAndIntervals(); resizeTimeoutId = setTimeout(commitResize, 300 ); } function commitResize(){ if(canvas){ canvasContainer.removeChild(canvas); } canvas = document.createElement('canvas'); canvas.style.position = "absolute"; context = canvas.getContext("2d"); canvasContainer.appendChild(canvas); htmlBounds = new Sakri.Geom.Rectangle(0,0, getWidth(canvasContainer) , getHeight(canvasContainer)); if(htmlBounds.width >= maxStageWidth){ canvas.width = maxStageWidth; canvas.style.left = htmlBounds.getCenterX() - (maxStageWidth/2)+"px"; }else{ canvas.width = htmlBounds.width; canvas.style.left ="0px"; } if(htmlBounds.height > maxStageHeight){ canvas.height = maxStageHeight; canvas.style.top = htmlBounds.getCenterY() - (maxStageHeight/2)+"px"; }else{ canvas.height = htmlBounds.height; canvas.style.top ="0px"; } bounds = new Sakri.Geom.Rectangle(0,0, canvas.width, canvas.height); context.clearRect(0,0,canvas.width, canvas.height); if(bounds.width<minimumStageWidth || bounds.height<minimumStageHeight){ stageTooSmallHandler(); return; } var textInputSpan = document.getElementById("textInputSpan"); textInputSpan.style.top = htmlBounds.getCenterY() + (bounds.height/2) + 20 +"px"; textInputSpan.style.left = (htmlBounds.getCenterX() - getWidth(textInputSpan)/2)+"px"; startDemo(); } function stageTooSmallHandler(){ var warning = "Sorry, bigger screen required :("; context.font = "bold normal 24px sans-serif"; context.fillText(warning, bounds.getCenterX() - context.measureText(warning).width/2, bounds.getCenterY()-12); } //======================== //Demo specific properties //======================== var animating = false; var particles = []; var numParticles = 4000; var currentText = "SAKRI"; var fontRect; var fontProperties = new Sakri.CanvasTextProperties(Sakri.CanvasTextProperties.BOLD, null, 100); var animator; var particleSource = new Sakri.Geom.Point();; var particleSourceStart = new Sakri.Geom.Point(); var particleSourceTarget = new Sakri.Geom.Point(); var redParticles = ["#fe7a51" , "#fdd039" , "#fd3141"]; var greenParticles = ["#dbffa6" , "#fcf8fd" , "#99de5e"]; var pinkParticles = ["#fef4f7" , "#f2a0c0" , "#fb3c78"]; var yellowParticles = ["#fdfbd5" , "#fff124" , "#f4990e"]; var blueParticles = ["#9ca2df" , "#222a6d" , "#333b8d"]; var particleColorSets = [redParticles, greenParticles, pinkParticles, yellowParticles, blueParticles]; var particleColorIndex = 0; var renderParticleFunction; var renderBounds; var particleCountOptions = [2000, 4000, 6000, 8000, 10000, 15000, 20000 ]; var pixelParticleCountOptions = [10000, 40000, 60000, 80000, 100000, 150000 ]; function clearTimeoutsAndIntervals(){ animating = false; } function startDemo(){ //makes sure we don't try to access pixels outside of the canvas renderBounds = bounds.clone(); renderBounds.x += 10; renderBounds.y += 10; renderBounds.width -= 20; renderBounds.height -= 20; switch(document.getElementById("strategySelect").value){ case "drawRect": renderParticleFunction = renderParticlesDrawRect; setParticleNumberOptions(particleCountOptions); numParticles = parseInt(document.getElementById("particlesSelect").value); createParticles(); break; case "drawRectColor": renderParticleFunction = renderParticlesDrawRectWithColor; setParticleNumberOptions(particleCountOptions); numParticles = parseInt(document.getElementById("particlesSelect").value); createDrawRectColorParticles(); break; case "perPixel": renderParticleFunction = renderParticlesPerPixel; setParticleNumberOptions(pixelParticleCountOptions); numParticles = parseInt(document.getElementById("particlesSelect").value); createParticles(); break; case "perPixelColor": renderParticleFunction = renderParticlesPerPixelColor; setParticleNumberOptions(pixelParticleCountOptions); numParticles = parseInt(document.getElementById("particlesSelect").value); createPixelColorParticles(); break; } fontRect = new Sakri.Geom.Rectangle(bounds.x + bounds.width*.1, 0, bounds.width - bounds.width*.2, bounds.height); fontProperties.fontSize = 100; fontProperties.fontSize = Sakri.CanvasTextUtil.getFontSizeForWidth(currentText, fontProperties, fontRect.width, canvas); fontRect.y = bounds.getCenterY() - fontProperties.fontSize/2; fontRect.height = fontProperties.fontSize; context.font = fontProperties.getFontString(); particleSource.x = particleSourceStart.x = Sakri.MathUtil.getRandomNumberInRange(fontRect.x, fontRect.getRight()); particleSource.y = particleSourceStart.y = Sakri.MathUtil.getRandomNumberInRange(fontRect.y, fontRect.getBottom()); animator = new Sakri.UnitAnimator(2000, canvas, animatorUpdate, animatorComplete); nextParticleSourceTween(); animating = true; loop(); } function nextParticleSourceTween(){ particleColorIndex++; particleColorIndex %= particleColorSets.length; particleSourceTarget.x = Sakri.MathUtil.getRandomNumberInRange(fontRect.x, fontRect.getRight()); particleSourceTarget.y = Sakri.MathUtil.getRandomNumberInRange(fontRect.y, fontRect.getBottom()); animator.setEasingFunction = Sakri.UnitAnimator.getRandomEasingFunction(); animator.start(); } function animatorUpdate(){ particleSource.x = particleSourceStart.x + (particleSourceTarget.x - particleSourceStart.x) * animator.getAnimationPercent(); particleSource.y = particleSourceStart.y + (particleSourceTarget.y - particleSourceStart.y) * animator.getAnimationPercent(); } function animatorComplete(){ particleSourceStart.x = particleSourceTarget.x; particleSourceStart.y = particleSourceTarget.y; setTimeout(nextParticleSourceTween, 100); } function getParticleColor(){ var set = particleColorSets[particleColorIndex]; return set[Math.floor(Math.random()*set.length)]; } function createDrawRectColorParticles(){ particles = []; for(var i=0; i<numParticles * 5; i+=5){ particles[i] = particleSource.x;//x particles[i+1] = particleSource.y;//y particles[i+2] = -5 + Math.random()*10;//xSpeed particles[i+3] = -5 + Math.random()*10;//ySpeed particles[i+4] = getParticleColor();//color } } function createParticles(){ particles = []; for(var i=0; i<numParticles * 4; i+=4){ particles[i] = particleSource.x;//x particles[i+1] = particleSource.y;//y particles[i+2] = -5 + Math.random()*10;//xSpeed particles[i+3] = -5 + Math.random()*10;//ySpeed } } function createPixelColorParticles(){ particles = []; var rgb; for(var i=0; i<numParticles * 7; i+=7){ particles[i] = particleSource.x;//x particles[i+1] = particleSource.y;//y particles[i+2] = -5 + Math.random()*10;//xSpeed particles[i+3] = -5 + Math.random()*10;//ySpeed rgb = Sakri.MathUtil.hexToRgb(getParticleColor()); particles[i+4] = rgb.r; particles[i+5] = rgb.g; particles[i+6] = rgb.b; } } function loop(){ if(!animating){ return; } stats.tick(); //fill bg context.fillStyle = "#000000"; context.globalAlpha = .05; context.fillRect(0,0,canvas.width, canvas.height); context.globalAlpha = 1; //render particles renderParticleFunction(); //render text context.globalAlpha = .5; context.fillStyle = "#000000"; context.fillText(currentText, fontRect.x, bounds.getCenterY() - fontProperties.fontSize/2); context.globalAlpha = 1; window.requestAnimationFrame(loop, canvas); } function renderParticlesDrawRectWithColor(){ for(var i=0; i<particles.length; i+=5 ){ particles[i] += particles[i+2]; particles[i+1] += particles[i+3]; particles[i+3] += .05; context.fillStyle = particles[i+4]; context.fillRect(particles[i], particles[i+1], 1, 1); if(!bounds.containsPoint(particles[i], particles[i+1] )){ particles[i] = particleSource.x;//x particles[i+1] = particleSource.y;//y particles[i+2] = -5 + Math.random()*10;//xSpeed particles[i+3] = -5 + Math.random()*10;//ySpeed particles[i+4] = getParticleColor();//color } } } function renderParticlesDrawRect(){ context.fillStyle = "#FFFFFF"; for(var i=0; i<particles.length; i+=4 ){ particles[i] += particles[i+2]; particles[i+1] += particles[i+3]; particles[i+3] += .05; context.fillRect(particles[i], particles[i+1], 1, 1); if(!bounds.containsPoint(particles[i], particles[i+1] )){ particles[i] = particleSource.x;//x particles[i+1] = particleSource.y;//y particles[i+2] = -5 + Math.random()*10;//xSpeed particles[i+3] = -5 + Math.random()*10;//ySpeed } } } function renderParticlesPerPixel(){ var imageData = context.getImageData(0, 0, canvas.width, canvas.height); var data = imageData.data; var rowWidth = imageData.width * 4; var index; var i, length = particles.length; for(i=0; i<length; i+=4 ){ particles[i] += particles[i+2]; particles[i+1] += particles[i+3]; particles[i+3] += .05; index = Math.round(particles[i]) * 4 + Math.round(particles[i+1]) * rowWidth; data[index] += 50; data[index + 1] += 50; data[index + 2] += 50; if(!renderBounds.containsPoint(particles[i], particles[i+1] )){ particles[i] = particleSource.x;//x particles[i+1] = particleSource.y;//y particles[i+2] = -5 + Math.random()*10;//xSpeed particles[i+3] = -5 + Math.random()*10;//ySpeed } } context.putImageData(imageData, 0, 0); } function renderParticlesPerPixelColor(){ var imageData = context.getImageData(0, 0, canvas.width, canvas.height); var data = imageData.data; var rowWidth = imageData.width * 4; var index; var i, rgb, length = particles.length; for(i=0; i<length; i+=7 ){ particles[i] += particles[i+2]; particles[i+1] += particles[i+3]; particles[i+3] += .05; index = Math.round(particles[i]) * 4 + Math.round(particles[i+1]) * rowWidth; data[index] = particles[i+4]; data[index + 1] = particles[i+5]; data[index + 2] = particles[i+6]; if(!renderBounds.containsPoint(particles[i], particles[i+1] )){ particles[i] = particleSource.x;//x particles[i+1] = particleSource.y;//y particles[i+2] = -5 + Math.random()*10;//xSpeed particles[i+3] = -5 + Math.random()*10;//ySpeed rgb = Sakri.MathUtil.hexToRgb(getParticleColor()); particles[i+4] = rgb.r; particles[i+5] = rgb.g; particles[i+6] = rgb.b; } } context.putImageData(imageData, 0, 0); } var maxCharacters = 10; function changeText(){ var textInput = document.getElementById("textInput"); if(textInput.value && textInput.text!=""){ if(textInput.value.length > maxCharacters){ alert("Sorry, there is only room for "+maxCharacters+" characters. Try a shorter name."); return; } if(textInput.value.indexOf(" ")>-1){ alert("Sorry, no support for spaces right now :("); return; } currentText = textInput.value; clearTimeoutsAndIntervals(); animating = false; setTimeout(commitResize, 100); } } function changeSettings(){ clearTimeoutsAndIntervals(); animating = false; setTimeout(commitResize, 100); } function setParticleNumberOptions(values){ var selector = document.getElementById("particlesSelect"); if(selector.options.length>0 && parseInt(selector.options[0].value) == values[0] ){ return; } while(selector.options.length){ selector.remove(selector.options.length-1); } for(var i=0;i <values.length; i++){ selector.options[i] = new Option(values[i], values[i], i==0, i==0); } }
Particles - Script Codes
Particles - Script Codes
Home Page Home
Developer Sakri Rosenstrom
Username sakri
Uploaded September 13, 2022
Rating 4
Size 9,207 Kb
Views 26,312
Do you need developer help for Particles?

Find the perfect freelance services for your business! Fiverr's mission is to change how the world works together. Fiverr connects businesses with freelancers offering digital services in 500+ categories. Find Developer!

Sakri Rosenstrom (sakri) Script Codes
Create amazing Facebook ads with AI!

Jasper is the AI Content Generator that helps you and your team break through creative blocks to create amazing, original content 10X faster. Discover all the ways the Jasper AI Content Platform can help streamline your creative workflows. Start For Free!