From 5a1c06798e43de7036bca480c0b8d025ae1d780d Mon Sep 17 00:00:00 2001 From: George Michael Brower Date: Fri, 28 Jan 2011 13:26:38 -0700 Subject: [PATCH] Commented up the source to FizzyText and added setName to the pre on index.html --- demo/demo.css | 9 +-- demo/demo.js | 152 +++++++++++++++++++++++++++++++++----------------- index.html | 34 ++++++++++- 3 files changed, 136 insertions(+), 59 deletions(-) diff --git a/demo/demo.css b/demo/demo.css index 770cf17..249401c 100644 --- a/demo/demo.css +++ b/demo/demo.css @@ -107,12 +107,9 @@ footer { pre a:link, pre a:visited, -pre a:active { -color: #ccc; -} - +pre a:active, pre a:hover { -color: #e61d5f; + color: #ccc; } code { @@ -128,7 +125,7 @@ code strong { .str { color: #0fa954; } .kwd { color: #e61d5f; } .com { color: #555; } -.typ { color: #606; } +.typ { color: #ccc; } .lit { color: #00aeff; } .pun, .opn, .clo { color: #777; } .pln { color: #ccc; } diff --git a/demo/demo.js b/demo/demo.js index 1029d3f..9ac306c 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -1,31 +1,58 @@ function FizzyText(message) { + // These are the variables that we manipulate with gui-dat. + // Notice they're all defined with "this". That makes them public. + // Otherwise, gui-dat can't see them. + + this.growthSpeed = 0.5; // how fast do particles change size? + this.maxSize = 3.2; // how big can they get? + this.noiseStrength = 10; // how turbulent is the flow? + this.speed = 0.4; // how fast do particles move? + this.displayOutline = false; // should we draw the message as a stroke? + + // __defineGetter__ and __defineSetter__ makes JavaScript believe that + // we've defined a variable 'this.message'. This way, whenever we + // change the message variable, we can call some more functions. + + this.__defineGetter__("message", function () { + return message; + }); + + this.__defineSetter__("message", function (m) { + message = m; + createBitmap(message); + }); + + // We can even add functions to the GUI! As long as they have + // 0 arguments, we can call them from the dat-gui panel. + + this.explode = function() { + var mag = Math.random()*30+30; + for (var i in particles) { + var angle= Math.random()*Math.PI*2; + particles[i].vx = Math.cos(angle)*mag; + particles[i].vy = Math.sin(angle)*mag; + } + }; + + //////////////////////////////////////////////////////////////// + var _this = this; var width = 550; var height = 200; var textAscent = 82; - var textLeft = 80; - - - this.growthSpeed = 0.5; - this.minSize = 0; - this.maxSize = 3.2; - - this.noiseScale = 300; - this.noiseStrength = 10; - this.speed = 0.4; - - this.displayOutline = false; - - this.textAscent = textAscent; - - + var textOffsetLeft = 80; + var noiseScale = 300; + var colors = ["#00aeff", "#0fa954", "#54396e", "#e61d5f"]; - + + // This is the context we use to get a bitmap of text using + // the getImageData function. var r = document.createElement('canvas'); var s = r.getContext('2d'); + // This is the context we actually use to draw. var c = document.createElement('canvas'); var g = c.getContext('2d'); @@ -34,24 +61,33 @@ function FizzyText(message) { r.setAttribute('height', height); c.setAttribute('height', height); + // Add our demo to the HTML document.getElementById('helvetica-demo').appendChild(c); + // Stores bitmap image var pixels = []; + + // Stores a list of particles var particles = []; + // Set g.font to the same font as the bitmap canvas, incase we + // want to draw some outlines. s.font = g.font = "800 " + textAscent + "px helvetica, arial, sans-serif"; - // Set reference onto particles + // Instantiate some particles for (var i = 0; i < 1000; i++) { particles.push(new Particle(Math.random() * width, Math.random() * height)); } - var createBitmap = function (m) { + // This function creates a bitmap of pixels based on your message + // It's called every time we change the message property. + var createBitmap = function (msg) { + s.fillStyle = "#fff"; s.fillRect(0, 0, width, height); s.fillStyle = "#222"; - s.fillText(m, textLeft, textAscent); + s.fillText(msg, textOffsetLeft, textAscent); // Pull reference var imageData = s.getImageData(0, 0, width, height); @@ -59,6 +95,7 @@ function FizzyText(message) { }; + // Called once per frame, updates the animation. var render = function () { g.clearRect(0, 0, width, height); @@ -67,7 +104,7 @@ function FizzyText(message) { g.globalCompositeOperation = "source-over"; g.strokeStyle = "#000"; g.lineWidth = .5; - g.strokeText(message, textLeft, textAscent); + g.strokeText(message, textOffsetLeft, textAscent); } g.globalCompositeOperation = "darker"; @@ -79,6 +116,7 @@ function FizzyText(message) { }; + // Returns x, y coordinates for a given index in the pixel array. var getPosition = function (i) { return { x: (i - (width * 4) * Math.floor(i / (width * 4))) / 4, @@ -86,6 +124,7 @@ function FizzyText(message) { }; }; + // Returns a color for a given pixel in the pixel array. var getColor = function (x, y) { var base = (Math.floor(y) * width + Math.floor(x)) * 4; var c = { @@ -97,67 +136,78 @@ function FizzyText(message) { return "rgb(" + c.r + "," + c.g + "," + c.b + ")"; }; - - this.__defineGetter__("message", function () { - return message; - }); - - this.__defineSetter__("message", function (m) { - message = m; - createBitmap(message); - }); - - this.explode = function() { - var mag = Math.random()*30+30; - for (var i in particles) { - var angle= Math.random()*Math.PI*2; - particles[i].vx = Math.cos(angle)*mag; - particles[i].vy = Math.sin(angle)*mag; - } - }; + // This calls the setter we've defined above, so it also calls + // the createBitmap function. this.message = message; + // This calls the render function every 30 milliseconds. setInterval(render, 30); + // This class is responsible for drawing and moving those little + // colored dots. function Particle(x, y, c) { + + // Position this.x = x; this.y = y; + // Size of particle + this.r = 0; + + // This velocity is used by the explode function. this.vx = 0; this.vy = 0; - this.r = 0; - + + // Called every frame this.render = function () { - var c = getColor(this.x, this.y); - var angle = noise(this.x / _this.noiseScale, this.y / _this.noiseScale) * _this.noiseStrength; + // What color is the pixel we're sitting on top of? + var c = getColor(this.x, this.y); + + // Where should we move? + var angle = noise(this.x / noiseScale, this.y / noiseScale) * _this.noiseStrength; + + // Are we within the boundaries of the image? var onScreen = this.x > 0 && this.x < width && this.y > 0 && this.y < height; - var isBlack = c != "rgb(255,255,255)" && - onScreen; + + var isBlack = c != "rgb(255,255,255)" && onScreen; + // If we're on top of a black pixel, grow. + // If not, shrink. if (isBlack) { this.r += _this.growthSpeed; } else { this.r -= _this.growthSpeed; } + + // This velocity is used by the explode function. this.vx *= 0.5; this.vy *= 0.5; + + // Change our position based on the flow field and our + // explode velocity. this.x += Math.cos(angle) * _this.speed + this.vx; - this.y += -Math.sin(angle) * _this.speed + this.vy; - this.r = constrain(this.r, _this.minSize, _this.maxSize); - if (this.r <= _this.minSize) { + this.y += -Math.sin(angle) * _this.speed + this.vy; + + this.r = constrain(this.r, 0, _this.maxSize); + + // If we're tiny, keep moving around until we find a black + // pixel. + if (this.r <= 0) { this.x = Math.random() * width; this.y = Math.random() * height; + return; // Don't draw! } - if (this.r <= 0) { - return; - } + + // Draw the circle. g.beginPath(); g.arc(this.x, this.y, this.r, 0, Math.PI * 2, false); g.fill(); + } + } var constrain = function (v, o1, o2) { diff --git a/index.html b/index.html index 0e32d4a..2981c69 100644 --- a/index.html +++ b/index.html @@ -4,12 +4,14 @@ +