Skip to content

Instantly share code, notes, and snippets.

@dgb
Created March 1, 2011 04:38
Show Gist options
  • Save dgb/848616 to your computer and use it in GitHub Desktop.
Save dgb/848616 to your computer and use it in GitHub Desktop.
Refactored Canvas AJAX Spinner
/*
Ajax spinning indicator. The constructor accepts two arguments:
element - the canvas element of the spinner
options - an object of options that are initialized with the instance
- check out the code to see what options you have :P
This thing is more or less refactored from Adam's work:
http://starkravingcoder.blogspot.com/2007/09/canvas-loading-indicator.html
No license was specified by Adam, so as a sort-of derivitive work,
I'm not going to specify any particular license.
*/
function Spinner(element, options){
this.context = element.getContext("2d");
this.animating = false;
this.currentOffset = 0;
this.options = {
bars: 10,
center:{
x:100,
y:100
},
innerRadius:10,
size:{
width:3,
height:12
},
color:{
red:0,
green:17,
blue:58
}
};
for(o in options){
this.options[o] = options[o];
}
}
Spinner.prototype.makeRGBA = function(){
return "rgba(" + [].slice.call(arguments, 0).join(",") + ")";
}
Spinner.prototype.drawBlock = function(bar){
var color = this.options.color,
bars = this.options.bars,
size = this.options.size;
this.context.fillStyle = this.makeRGBA(color.red, color.green, color.blue, (bars+1-bar)/(bars+1));
this.context.fillRect(-size.width/2, 0, size.width, size.height);
}
Spinner.prototype.calculateAngle = function(bar){
return 2 * bar * Math.PI / this.options.bars;
}
Spinner.prototype.calculatePosition = function(bar){
var angle = this.calculateAngle(bar);
var innerRadius = this.options.innerRadius;
return {
y: (innerRadius * Math.cos(-angle)),
x: (innerRadius * Math.sin(-angle)),
angle: angle
};
}
Spinner.prototype.draw = function(offset) {
var context = this.context,
center = this.options.center,
bars = this.options.bars;
this.clearFrame();
context.save();
context.translate(center.x, center.y);
for(var i = 0; i<bars; i++){
var bar = (offset+i) % bars,
pos = this.calculatePosition(bar);
context.save();
context.translate(pos.x, pos.y);
context.rotate(pos.angle);
this.drawBlock(i);
context.restore();
}
context.restore();
}
Spinner.prototype.clearFrame = function(){
var context = this.context;
context.clearRect(0, 0, context.canvas.clientWidth, context.canvas.clientHeight);
}
Spinner.prototype.nextAnimation = function(){
if (!this.animating){
return;
};
this.currentOffset = (this.currentOffset + 1) % this.options.bars;
this.draw(this.currentOffset);
var self = this;
this.timer = window.setTimeout(function(){self.nextAnimation()}, 50);
}
Spinner.prototype.stop = function(){
this.animating = false;
this.clearFrame();
clearTimeout(this.timer);
}
Spinner.prototype.start = function(){
this.animating = true;
this.nextAnimation();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment