From 4a46aa024e633be9ce9e0cfe01ba8fd0503f2620 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Berg=C3=A9?= Date: Thu, 25 Apr 2013 10:10:28 +0200 Subject: [PATCH] update to v0.2.0, api changes, retina support, text, initial circle --- README.md | 47 +++++++++++------ circular-progress.js | 122 ++++++++++++++++++++++++++++++++++++------- component.json | 4 +- test/index.html | 84 +++++++++++++++++++++++++++++ 4 files changed, 219 insertions(+), 38 deletions(-) create mode 100644 test/index.html diff --git a/README.md b/README.md index adb981c..cab0253 100644 --- a/README.md +++ b/README.md @@ -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. \ No newline at end of file +Update percent and draw the canvas, `value` must be a float between 0 and 100. \ No newline at end of file diff --git a/circular-progress.js b/circular-progress.js index a685ae9..b9f6b44 100644 --- a/circular-progress.js +++ b/circular-progress.js @@ -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); \ No newline at end of file diff --git a/component.json b/component.json index 2c84a23..c3e18c5 100644 --- a/component.json +++ b/component.json @@ -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" } \ No newline at end of file diff --git a/test/index.html b/test/index.html new file mode 100644 index 0000000..7885eaf --- /dev/null +++ b/test/index.html @@ -0,0 +1,84 @@ + + + + Circular Progress test + + + + + + + \ No newline at end of file