Skip to content
Open
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ Specify options like in example above.
| startAngle | Initial angle (for `0` value) <br> Default: `-Math.PI` |
| reverse | Reverse animation and arc draw <br> Default: `false` |
| thickness | Width of the arc. By default it's automatically calculated as 1/14 of `size` but you may set your own number <br> Default: `"auto"` |
| emptyThickness | Width of the empty arc. By default it falls back to the `thickness` parameter <br> Default: `"auto"` |
| lineCap | Arc line cap: `"butt"`, `"round"` or `"square"` - [read more](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D.lineCap) <br> Default: `"butt"`
| fill | The arc fill config. You may specify next: <br>- `"#ff1e41"` <br>- `{ color: "#ff1e41" }` <br>- `{ color: 'rgba(255, 255, 255, .3)' }` <br>- `{ gradient: ["red", "green", "blue"] }` <br>- `{ gradient: [["red", .2], ["green", .3], ["blue", .8]] }` <br>- `{ gradient: [ ... ], gradientAngle: Math.PI / 4 }` <br>- `{ gradient: [ ... ], gradientDirection: [x0, y0, x1, y1] }` <br>- `{ image: "http://i.imgur.com/pT0i89v.png" }`<br>- `{ image: imageInstance }`<br>- `{ color: "lime", image: "http://i.imgur.com/pT0i89v.png" }` <br> Default: `{ gradient: ["#3aeabb", "#fdd250"] }` |
| emptyFill | Color of the "empty" arc. Only a color fill supported by now <br> Default: `"rgba(0, 0, 0, .1)"` |
Expand Down Expand Up @@ -255,7 +256,7 @@ npm install
### Modify

You need to update `dist/circle-progress.min.js` after any change to `dist/circle-progress.js`:

```sh
npm run build-min
```
Expand Down Expand Up @@ -298,5 +299,5 @@ They will be generated in `docs/api/`.
* release on Bower: just create a Git tag (e.g.): `git tag v1.2.3 && git push --tags`
* release on GitHub - add release notes to the Git tag
* release on NPM: `npm publish`, but be aware:

> Once a package is published with a given name and version, that specific name and version combination can never be used again - [NPM docs](https://docs.npmjs.com/cli/publish)
46 changes: 35 additions & 11 deletions dist/circle-progress.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@
*/
thickness: 'auto',

/**
* Width of the empty arc (under the filled one) in pixels.
* If it's `'auto'`, it falls back to the value of the `thickness` property.
* @type {number|string}
* @default 'auto'
*/
emptyThickness: 'auto',

/**
* Fill of the arc. You may set it to:
*
Expand Down Expand Up @@ -342,16 +350,17 @@

var ctx = this.ctx,
r = this.radius,
arcR = this.getArcRadius(),
t = this.getThickness(),
a = this.startAngle;

ctx.save();
ctx.beginPath();

if (!this.reverse) {
ctx.arc(r, r, r - t / 2, a, a + Math.PI * 2 * v);
ctx.arc(r, r, arcR, a, a + Math.PI * 2 * v);
} else {
ctx.arc(r, r, r - t / 2, a - Math.PI * 2 * v, a);
ctx.arc(r, r, arcR, a - Math.PI * 2 * v, a);
}

ctx.lineWidth = t;
Expand All @@ -369,21 +378,17 @@
drawEmptyArc: function(v) {
var ctx = this.ctx,
r = this.radius,
t = this.getThickness(),
a = this.startAngle;
arcR = this.getArcRadius(),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like that there're this.radius and this.getArcRadious() at the same time.

  • Since the radius is not equal to this.size / 2 anymore - I'd get rid of this.radius.
  • Also, I'd rename the method to this.getRadius(), because it affects both arc & BG circle.

Copy link
Author

@monovertex monovertex Sep 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I left this.radius just to have easy access to this.size / 2, as I need that in order to calculate the actual radius and the x, y coords for the circle.

I could either calculate the half coords everytime in drawArc and drawEmptyArc, as well as getArcRadius, or rename this.radius to something like this.halfSize, and use that instead of this.radius, just to avoid unnecessary math operations.

What do you think?

Copy link
Owner

@kottenator kottenator Sep 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This variable needs to be updated when this.size is changed. I'd rather drop it. There are only 2 places where it'd get replaced with this.size / 2.

Also, I still think it's reasonable to rename your getArcRadius method into getRadius.

I suggest the following naming:

// ...
var c = this.size / 2, // center X/Y coords
  r = this.getRadius(),
  t = this.getThickness(),
  a = this.startAngle;
// ...
ctx.arc(c, c, r, a, a + Math.PI * 2 * v);

t = this.getEmptyThickness();

if (v < 1) {
ctx.save();
ctx.beginPath();

if (v <= 0) {
ctx.arc(r, r, r - t / 2, 0, Math.PI * 2);
if (this.reverse) {
ctx.arc(r, r, arcR, 0, Math.PI * 2);
} else {
if (!this.reverse) {
ctx.arc(r, r, r - t / 2, a + Math.PI * 2 * v, a);
} else {
ctx.arc(r, r, r - t / 2, a, a - Math.PI * 2 * v);
}
ctx.arc(r, r, arcR, Math.PI * 2, 0);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line, as well as the whole if...else is not needed anymore.

}

ctx.lineWidth = t;
Expand Down Expand Up @@ -441,6 +446,25 @@
return $.isNumeric(this.thickness) ? this.thickness : this.size / 14;
},

/**
* Get the empty arc thickness.
* @see CircleProgress#emptyThickness
* @protected
* @returns {number}
*/
getEmptyThickness: function() {
return $.isNumeric(this.emptyThickness) ? this.emptyThickness : this.getThickness();
},

/**
* Returns the real arc radius, after the thickness has been accounted for.
* @private
* @returns {number}
*/
getArcRadius: function() {
return this.radius - Math.max(this.getThickness(), this.getEmptyThickness()) / 2;
},

/**
* Get current value.
* @protected
Expand Down
2 changes: 1 addition & 1 deletion dist/circle-progress.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions docs/examples.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,20 @@
// "data-" attributes are taken into account only on init (not on update/redraw)
// "data-fill" (and other object options) should be in valid JSON format
});

/*
* Example 6:
*
* - custom gradient
* - different thicknesses
*/
var c6 = $('.sixth.circle');

c6.circleProgress({
value: 0.75,
lineCap: 'round',
emptyThickness: 15,
thickness: 5,
fill: {gradient: ['#f4ad60', '#fffaaa']}
});
})(jQuery);
4 changes: 4 additions & 0 deletions docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ <h1 class="page-title">
<span>custom angle, <br> value update</span>
</div>

<div class="sixth circle">
<span>different thicknesses</span>
</div>

<div
class="fifth circle"
data-value="0.9"
Expand Down
79 changes: 76 additions & 3 deletions tests/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,49 @@
}).circleProgress('widget');
var defaultSize = $.circleProgress.defaults.size;

assert.pixelHex(canvas, 1, defaultSize / 2 - 1, color);
assert.pixelHex(canvas, defaultSize - 1, defaultSize / 2 - 1, color);
assert.pixelHex(canvas, 2, defaultSize / 2 - 1, color);
assert.pixelHex(canvas, defaultSize - 2, defaultSize / 2 - 1, color);
});

QUnit.test("Test circle with emptyThickness < thickness", function(assert) {
var color = '#ff0000';
var emptyColor = '#00ff00';
var thickness = 4;
var emptyThickness = 2;

var canvas = createCircle({
value: 0.5,
thickness: thickness,
emptyThickness: emptyThickness,
fill: { color: color },
emptyFill: emptyColor,
animation: false
}).circleProgress('widget');
var defaultSize = $.circleProgress.defaults.size;

assert.pixelHex(canvas, defaultSize / 2 - 1, 1, color);
assert.pixelHex(canvas, defaultSize / 2 - 1, defaultSize - thickness / 2, emptyColor);
});

QUnit.test("Test circle with emptyThickness > thickness", function(assert) {
var color = '#ff0000';
var emptyColor = '#00ff00';
var thickness = 5;
var emptyThickness = 10;

var canvas = createCircle({
value: 0.5,
thickness: thickness,
emptyThickness: emptyThickness,
fill: { color: color },
emptyFill: emptyColor,
animation: false
}).circleProgress('widget');
var defaultSize = $.circleProgress.defaults.size;

assert.pixelHex(canvas, defaultSize / 2 - 1, 1, emptyColor);
assert.pixelHex(canvas, defaultSize / 2 - 1, defaultSize - emptyThickness / 2, emptyColor);
assert.pixelHex(canvas, defaultSize / 2 - 1, emptyThickness / 2, color);
});

QUnit.module("Layout tests with animation");
Expand Down Expand Up @@ -264,4 +305,36 @@
assert.equal(50, $(canvas).height());
assert.equal(50, canvas.width);
});
})();

QUnit.module("Value tests");

QUnit.test("Test that `emptyThickness` defaults to `thickness`", function (assert) {
var thickness = 10;
var canvas = createCircle({
value: 0,
thickness: thickness
});

assert.strictEqual(canvas.data('circle-progress').getEmptyThickness(), thickness);
});

$.each([
[1, 10],
[6, 6],
[20, 0.1]
], function (i, testData) {
var thickness = testData[0],
emptyThickness = testData[1],
defaultSize = $.circleProgress.defaults.size;;

QUnit.test("Test that the arc radius is properly calculated with thickness = " + String(thickness) + " and emptyThickness = " + String(emptyThickness), function (assert) {
var canvas = createCircle({
thickness: thickness,
emptyThickness: emptyThickness
});

assert.strictEqual(canvas.data('circle-progress').getArcRadius(),
(defaultSize - Math.max(emptyThickness, thickness)) / 2);
});
});
})();