Created
September 18, 2011 07:27
-
-
Save pharrington/1224842 to your computer and use it in GitHub Desktop.
JavaScript/Canvas pulser
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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