// Defaults color BackgroundColor = 0xFFCCCCCC; color BlackColor = 0xFF000000; color DefaultTextColor = 0xFF333333; color FrameTextColor = 0xFF3333FF; PFont DefaultFont = createFont("Oswald", 38, true); function AnimationFrameClass () {} AnimationFrameClass.prototype = { data: null, // optional data (for internal use of children) draw: null, // required, the function to render this animation onend: null, // optional function to call, when animation is finished // required function to indicate when to stop, by default after max_frames finished: function() { return this.max_frames < this.frame; }, max_frames: 100, // default maximum number of frames for this animation name: null, // the name of the animation, useful for debugging reset: function() { // restart the frame counter this.frame = 0; }, onstart: null, // optional function to call, before animation begins started: false, // used by draw function frame: 0 // required, the frame counter }; function inherit(C, P, p) { var F = function () {}; F.prototype = P.prototype; C.prototype = new F(); C.uber = P.prototype; C.uber_constructor = P; C.prototype.constructor = C; if (p) { for (var prop in p) { if (p.hasOwnProperty(prop)) { C.prototype[prop] = p[prop]; } } } return C; } var BackgroundAnim = inherit(function() {}, AnimationFrameClass, { draw: function() { background(BackgroundColor); }, finished: function() { return false; // present on all frames, does not stop }, name: 'Background Animation' }); var Queue = []; void setup() { size(500, 500); } // called automatically by processing continuing the animation, draws a frame void draw() { var newQueue = [], i = 0, j = Queue.length, animObj; for (; i < j; i += 1) { // clear fill and stroke that may have been set by previous animations noFill(); noStroke(); animObj = Queue[i]; // fire started function if (!animObj.started) { animObj.started = true; animObj.onstart && animObj.onstart(); } // draw and increment the frame animObj.draw(); animObj.frame += 1; // fire the end function if (animObj.finished()) { animObj.onend && animObj.onend(); } // this animation stays in the queue for the next frame else { newQueue.push(animObj); } } Queue = newQueue; } // ANIMATIONS // draws text at the x/y position. can fade in and out var TextAnim = inherit(function(text, x, y, cfg) { var conf = cfg || {}; this.data = [text, x, y]; this.fadeIn = conf.fadeIn; this.fadeOut = conf.fadeOut; this.font = conf.font || DefaultFont; this.color = conf.color || DefaultTextColor; }, AnimationFrameClass, { draw: function() { var alpha = 256; if (200 > this.frame && this.fadeIn) { alpha = alpha * this.frame / 200; } else if (800 < this.frame && this.fadeOut) { alpha = alpha * (1000 - this.frame) / 200; } textFont(this.font); fill(this.color, alpha); text.apply(this, this.data); }, max_frames: 1000 }); // draws a circle with a black stroke var CircleAnim = inherit(function(x, y, width, height, cfg) { var conf = cfg || {}; this.data = [x, y, width, height]; this.color = conf.color || BackgroundColor; this.strokeColor = conf.strokeColor || BlackColor; }, AnimationFrameClass, { draw: function() { fill(this.color, 256); stroke(this.strokeColor, 256); ellipse.apply(this, this.data); }, finished: function() { return false; } }); // draws a curved line var BezierAnim = inherit(function(x1, y1, cx1, cy1, cx2, cy2, x2, y2, cfg) { var conf = cfg || {}; this.data = [x1, y1, cx1, cy1, cx2, cy2, x2, y2]; this.color = conf.color || BackgroundColor; this.strokeColor = conf.strokeColor || BlackColor; }, AnimationFrameClass, { draw: function() { fill(this.color, 256); stroke(this.strokeColor, 256); bezier.apply(this, this.data); }, finished: function() { return false; } }); // draws the blink var BlinkAnim = inherit(function() { BlinkAnim.uber_constructor.apply(this, arguments); this.originalData = []; // clone for manipulation for (var i = 0, j = this.data.length; i < j; i += 1) { this.originalData[i] = this.data[i]; } }, BezierAnim, { draw: function() { var frameCycle = this.frame % 100; this.data[1] = this.originalData[3] + frameCycle / 4; this.data[7] = this.originalData[5] + frameCycle / 4; BlinkAnim.uber.draw.call(this); } }); // prints the frame count, uses onstart to setup some initial variables var FrameCountAnim = inherit(function() { this.font = createFont("Helvetica", 12, true); }, AnimationFrameClass, { draw: function() { var current_seconds = (new Date()).getSeconds(); if (this.current_second != current_seconds) { this.frames_per_second = (this.frame - this.frame_count_at); this.current_second = current_seconds; this.frame_count_at = this.frame; } textFont(this.font); fill(FrameTextColor, 256); text('current frame = ' + this.frame + ', frames/sec = ' + this.frames_per_second, 250, 15); }, finished: function() { return false; }, onstart: function() { this.current_second = (new Date()).getSeconds(); this.frame_count_at = 0; this.frames_per_second = 0; } }); Queue.push(new BackgroundAnim()); Queue.push(new TextAnim( "Hello World! (1000 frames)", 25, 50, {fadeIn: 1, fadeOut: 1})); Queue.push(new FrameCountAnim()); Queue.push(new CircleAnim(250, 250, 200, 200, {color: 0xFFFFFFFF})); Queue.push(new CircleAnim(210, 225, 25, 25, {color: 0xFFFEFEFE})); Queue.push(new CircleAnim(210, 225, 10, 10, {color: 0xFF333399})); Queue.push(new CircleAnim(290, 225, 25, 25, {color: 0xFFFEFEFE})); Queue.push(new CircleAnim(290, 225, 10, 10, {color: 0xFF333399})); Queue.push(new BezierAnim(210, 290, 240, 310, 260, 310, 290, 290)); Queue.push(new BlinkAnim(195, 210, 205, 210, 215, 210, 225, 210));