Skip to content

Commit

Permalink
update to v0.2.0, api changes, retina support, text, initial circle
Browse files Browse the repository at this point in the history
  • Loading branch information
gregberge committed Apr 25, 2013
1 parent 0ae83de commit 4a46aa0
Show file tree
Hide file tree
Showing 4 changed files with 219 additions and 38 deletions.
47 changes: 31 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,51 @@
# Circular progress
# Circular Progress

A JavaScript circular progress bar widget, dependency-free and configurable.
A JavaScript circular progress widget, dependency-free and configurable.

## Example

```javascript
var progressBar = new CircularProgress({
width: 200,
height: 200,
var progress = new CircularProgress({
radius: 70,
strokeStyle: '#000',
strokeStyle: 'black',
lineCap: 'round',
lineWidth: '4.0'
lineWidth: 4
});

document.body.appendChild(progressBar.canvas);
document.body.appendChild(progress.canvas);

progressBar.progress(0.4);
progress.update(40);
```

## Usage

### new CircularProgress( options )

Options must contains :
Other attributes are attached to the canvas 2D context.

* `width`
* `height`
* `radius`
Options :

Other attributes are attached to the canvas 2D context.
* all 2D context properties.
* `text` : Scopped to text, accept `value` and all 2D context properties.
* `initial` : Scopped to initial circle, accept all 2D context properties.

Example :

```javascript
progress = new CircularProgress({
lineWidth: 2,
initial: {
strokeStyle: 'gray',
lineWidth: 4
}
});

// update options
progress.options.text = {
font: '14px'
};
```

### progress( value )
### update( value )

Notify the progress, and draw the canvas, `value` is a float between 0 and 1.
Update percent and draw the canvas, `value` must be a float between 0 and 100.
122 changes: 102 additions & 20 deletions circular-progress.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,115 @@
(function () {
var circ = Math.PI * 2,
quart = Math.PI / 2;
var autoscale, extendCtx, ctxProperties, CircularProgress;

this.CircularProgress = function (options) {
if (! options.width || ! options.height || ! options.radius) {
return ;
}
ctxProperties = ['fillStyle', 'font', 'globalAlpha', 'globalCompositeOperation',
'lineCap', 'lineDashOffset', 'lineJoin', 'lineWidth',
'miterLimit', 'shadowBlur', 'shadowColor', 'shadowOffsetX',
'shadowOffsetY', 'strokeStyle', 'textAlign', 'textBaseLine'];

this.canvas = document.createElement('canvas');
this.canvas.width = options.width;
this.canvas.height = options.height;
// autoscale function from https://github.com/component/autoscale-canvas
autoscale = function (canvas) {
var ctx = canvas.getContext('2d'),
ratio = window.devicePixelRatio || 1;

this.radius = options.radius;
if (1 !== ratio) {
canvas.style.width = canvas.width + 'px';
canvas.style.height = canvas.height + 'px';
canvas.width *= ratio;
canvas.height *= ratio;
ctx.scale(ratio, ratio);
}

delete options.width;
delete options.height;
delete options.radius;
return canvas;
};

this.ctx = this.canvas.getContext('2d');
extendCtx = function (ctx, options) {
for (var i in options) {
console.log(i);
this.ctx[i] = options[i];
if (ctxProperties.indexOf(i) === -1) continue;

ctx[i] = options[i];
}
};

CircularProgress = this.CircularProgress = function (options) {
var ctx, i, property;

options = options || {};
this.el = document.createElement('canvas');

this.options = options;

options.text = options.text || {};
options.text.value = options.text.value || null;

ctx = this.el.getContext('2d');

for (i in ctxProperties) {
property = ctxProperties[i];
options[property]= typeof options[property] !== 'undefined' ? options[property] : ctx[property];
}

if (options.radius) this.radius(options.radius);
};

CircularProgress.prototype.update = function (value) {
this._percent = value;
this.draw();
return this;
};

CircularProgress.prototype.radius = function (value) {
var size = value * 2;
this.el.width = size;
this.el.height = size;
autoscale(this.el);
return this;
};

this.CircularProgress.prototype.progress = function (value) {
this.ctx.beginPath();
this.ctx.arc(this.canvas.width / 2, this.canvas.height / 2, this.radius, -(quart), ((circ) * value) - quart, false);
this.ctx.stroke();
CircularProgress.prototype.draw = function () {
var tw, text, fontSize,
options = this.options,
ctx = this.el.getContext('2d'),
percent = Math.min(this._percent, 100),
ratio = window.devicePixelRatio || 1,
angle = Math.PI * 2 * percent / 100,
size = this.el.width / ratio,
half = size / 2,
x = half,
y = half;

ctx.clearRect(0, 0, size, size);

// initial circle
if (options.initial) {
extendCtx(ctx, options);
extendCtx(ctx, options.initial);

ctx.beginPath();
ctx.arc(x, y, half - ctx.lineWidth, 0, 2 * Math.PI, false);
ctx.stroke();
}

// progress circle
extendCtx(ctx, options);

ctx.beginPath();
ctx.arc(x, y, half - ctx.lineWidth, 0, angle, false);
ctx.stroke();

// text
if (options.text) {
extendCtx(ctx, options);
extendCtx(ctx, options.text);
}

text = options.text.value === null ? (percent | 0) + '%' : '';
tw = ctx.measureText(text).width;
fontSize = ctx.font.match(/(\d+)px/);
fontSize = fontSize ? fontSize[1] : 0;

ctx.fillText(text, x - tw / 2 + 1, y + fontSize / 2 - 1);

return this;
};

}).call(this);
4 changes: 2 additions & 2 deletions component.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "circular-progress",
"description": "A JavaScript circular progress bar widget, dependency-free and configurable.",
"version": "0.1.0",
"description": "A JavaScript circular progress widget, dependency-free and configurable.",
"version": "0.2.0",
"main": "circular-progress.js"
}
84 changes: 84 additions & 0 deletions test/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<!DOCTYPE html>
<html>
<head>
<title>Circular Progress test</title>
<meta charset="utf-8">
</head>
<body>
<script src="../circular-progress.js"></script>
<script>
(function () {
var n, id, progress;

progress = new CircularProgress({
radius: 20
});

document.body.appendChild(progress.el);

n = 0;
id = setInterval(function () {
if (n == 100) clearInterval(id);
progress.update(n++);
}, 100);
})();

(function () {
var n, id, progress;

progress = new CircularProgress({
radius: 40,
lineWidth: 2,
strokeStyle: 'black',
initial: {
lineWidth: 4,
strokeStyle: 'gray'
}
});

document.body.appendChild(progress.el);

n = 0;
id = setInterval(function () {
if (n == 100) clearInterval(id);
progress.update(n++);
}, 70);
})();

(function () {
var n, id, progress;

progress = new CircularProgress({
radius: 70,
strokeStyle: 'black',
lineCap: 'square',
lineJoin: 'round',
lineWidth: 5,
shadowBlur: 0,
shadowColor: 'yellow',
text: {
font: 'bold 15px arial',
shadowBlur: 0
},
initial: {
strokeStyle: 'white',
lineCap: 'square',
lineJoin: 'round',
lineWidth: 5,
shadowBlur: 10,
shadowColor: 'black'
}
});

document.body.appendChild(progress.el);

n = 0;
id = setInterval(function () {
if (n == 100) clearInterval(id);
progress.update(n++);
}, 30);
})();

</script>
</body>
</html>

0 comments on commit 4a46aa0

Please sign in to comment.