Skip to content

Instantly share code, notes, and snippets.

@benshimmin
Last active August 29, 2015 14:05
Show Gist options
  • Save benshimmin/a5e3c4b6d0dc7ca073c8 to your computer and use it in GitHub Desktop.
Save benshimmin/a5e3c4b6d0dc7ca073c8 to your computer and use it in GitHub Desktop.
Simple canvas-based clock
// Depends on Underscore, nothing else.
// You could easily extend this to have proper hands, markers, numbers, etc.
var Clock = function(_params) {
var Utils = {
Maths : {
degreesToRadians : function(degrees) {
return degrees * Math.PI / 180;
}
}
};
function Point(x, y) {
this.x = x;
this.y = y;
}
// default params, should be fairly self-explanatory
var interval, c, r, params = {
time : 60,
bgColour : "#000000",
fgColour : "#ffffff",
cx : 50,
cy : 50,
radius : 50
};
var ctx = _params.ctx;
_.each(_params, function(value, key) {
if (_.has(params, key)) {
params[key] = value;
}
});
function Clock() {
c = new Point(params.cx, params.cy);
r = params.radius;
this.events = {};
this.draw();
_.bindAll(this, "begin", "on", "off", "trigger");
}
Clock.prototype.draw = function() {
// Draw the background
ctx.beginPath();
ctx.arc(c.x, c.y, r, 0, Math.PI * 2);
ctx.fillStyle = params.bgColour;
ctx.fill();
ctx.closePath();
};
var proto = Clock.prototype;
Clock.prototype.begin = function(scope, fn) {
var init = _.bind(function() {
interval = window.setInterval(_.bind(this.update, this), 10);
this.trigger("begin");
}, this);
if (scope && fn) {
scope[fn] = _.wrap(scope[fn], function(f) {
f();
init();
}, this);
} else {
init();
}
return this;
};
Clock.prototype.on = function(event, callback) {
this.events[event] = callback;
return this;
};
Clock.prototype.off = function(event) {
delete this.events[event];
return this;
};
Clock.prototype.trigger = function(event) {
if (_.has(this.events, event)) this.events[event]();
return this;
};
var angle = 271,
segment = 360 / params.time / 100,
startRadians = Utils.Maths.degreesToRadians(270);
Clock.prototype.update = function() {
var aRadians = Utils.Maths.degreesToRadians(angle += segment);
ctx.beginPath();
ctx.moveTo(c.x, c.y);
ctx.arc(c.x, c.y, r, startRadians, aRadians, false);
ctx.lineTo(c.x, c.y);
ctx.closePath();
ctx.fillStyle = params.fgColour;
ctx.fill();
if (angle >= 270 + 360) {
clearInterval(interval);
this.trigger("end");
}
};
Clock.prototype.reset = function() {
angle = 271;
this.draw();
this.trigger("reset");
};
return new Clock();
};
// Most basic: render and start a clock
var clock = new Clock({
ctx : document.getElementById("canvas").getContext("2d")
}).begin();
// Render a new clock with some params...
var clock2 = new Clock({
ctx : document.getElementById("canvas").getContext("2d"),
time : 10, // 10 seconds
cx : 250,
cy : 300
});
// Start the clock, and trigger a callback when the clock ends
clock2.begin().on("end", function() {
console.log("Time's up!");
});
// More advanced: you can also initialise the clock based on another
// function's being called:
var foo = {
triggerClock : function() {
console.log("I'll start a clock when I feel like it.");
}
};
clock2.begin(foo, "triggerClock"); // clock renders but does not start
foo.triggerClock(); // clock starts now
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment