Skip to content

Instantly share code, notes, and snippets.

@pharrington
Created September 18, 2011 07:27
Show Gist options
  • Save pharrington/1224842 to your computer and use it in GitHub Desktop.
Save pharrington/1224842 to your computer and use it in GitHub Desktop.
JavaScript/Canvas pulser
(function (global, undefined) {
var requestAnimFrame = (function () {
var rate = 16;
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function (callback) {
setTimeout(callback, rate);
}
})();
function fromColor(str) {
if (str[0] === "#") {
str = str.substr(1);
}
this.r = parseInt(str.substr(0, 2), 16);
this.g = parseInt(str.substr(2, 2), 16);
this.b = parseInt(str.substr(4, 2), 16);
this.a = 1;
}
/* new Color(int, int, int[, int]) or
* new Color(string)
*/
function Color(r, g, b, a) {
var source;
if (arguments.length === 1) {
if (typeof r === "string") {
fromColor.call(this, r);
return;
}
if (typeof r === "object") {
source = r;
r = source.r;
g = source.g;
b = source.b;
a = source.a;
}
}
this.r = r;
this.g = g;
this.b = b;
this.a = a === undefined ? 1 : a;
}
Color.prototype = {
toString: function () {
return "rgba(" +
this.r + "," +
this.g + "," +
this.b + "," +
this.a + ")";
}
};
// stolen from YUI3
function easeOut(t, start, delta, duration) {
return -delta *(t/=duration)*(t-2) + start;
}
function createCanvas(width, height, id) {
var canvas, context;
canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
if (id !== undefined) { canvas.id = id; }
context = canvas.getContext("2d");
return [canvas, context];
}
function pulse(context, size, startRadius, endRadius, thickness, color, endOpacity, duration, interval) {
var startOpacity = color.a,
start,
doFrame,
center = size / 2;
frameColor = new Color(color);
doFrame = function (time) {
time = time || new Date().getTime();
var elapsed = time - start,
opacity,
radius;
if (elapsed <= duration) {
radius = startRadius + easeOut(elapsed, startOpacity, endRadius - startRadius, duration);
opacity = easeOut(elapsed, startOpacity, endOpacity - startOpacity, duration);
frameColor.a = opacity;
context.clearRect(0, 0, size, size);
drawCircle(context, center, radius, thickness, frameColor);
requestAnimFrame(doFrame);
} else {
setTimeout(function () {
pulse(context, size, startRadius, endRadius, thickness, color, endOpacity, duration, interval);
}, interval);
}
};
start = new Date().getTime();
requestAnimFrame(doFrame);
}
function drawCircle(context, center, radius, thickness, color) {
context.strokeStyle = color.toString();
context.lineWidth = thickness;
context.beginPath();
context.arc(center, center, radius, Math.PI * 2, 0, true);
context.stroke();
}
global.Pulser = {
Color: Color,
create: function (properties) {
var endRadius = properties.radius * properties.scale,
size = Math.max(properties.radius * 2, endRadius * 2) + 1,
interval = properties.interval,
x = properties.x,
y = properties.y,
canctx = createCanvas(size, size),
canvas = canctx[0],
color = properties.color,
node = properties.parent || document.body;
if (interval === undefined) {
interval = 200;
}
if (color === undefined) {
color = new Color(0, 0, 255);
} else {
color = new Color(color);
}
canvas.style.position = "absolute";
canvas.style.left = (x - endRadius >>> 0) + "px";
canvas.style.top = (y - endRadius >>> 0) + "px";
node.appendChild(canvas);
pulse(canctx[1], size,
properties.radius, endRadius,
properties.thickness || 2,
color,
properties.endOpacity || 0,
properties.duration || 1000,
interval);
}
};
})(this);
addEventListener("load", function (e) {
/*
arguments:
x {Number} center X coordinate of the pulser
y {Number} center Y coordinate of the pulser
radius {Number} starting radius of the pulser
scale {Number} ratio of how much to grow the pulser
thickness {Number} pulser's thickness in pixels [default 2]
color {String or Pulser.Color} pulser's color [default #0000FF]
duration {Number} time in milliseconds the pulser takes to grow and fade
interval {Number} time in milliseconds before resetting the pulser
*/
Pulser.create({
x: 100,
y: 100,
color: "#FF0000",
radius: 25,
scale: 2,
thickness: 2,
duration: 1000,
interval: 200
});
}, false);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment