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 @@
+