├── .gitignore
├── tests
├── images
│ └── circle.png
├── index.html
├── test_utils.js
└── tests.js
├── jsdoc.conf
├── karma.conf.js
├── .travis.yml
├── bower.json
├── package.json
├── LICENSE
├── karma-saucelabs.conf.js
├── docs
├── index.html
├── styles.css
└── examples.js
├── dist
├── circle-progress.min.js
└── circle-progress.js
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | /.idea/
2 | /node_modules/
3 | /bower_components/
4 |
--------------------------------------------------------------------------------
/tests/images/circle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kottenator/jquery-circle-progress/HEAD/tests/images/circle.png
--------------------------------------------------------------------------------
/jsdoc.conf:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": ["plugins/markdown"],
3 | "opts": {
4 | "destination": "docs/api/"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration
2 | module.exports = function(config) {
3 | config.set({
4 | frameworks: ['qunit'],
5 | files: [
6 | {pattern: 'tests/images/circle.png', served: true, watched: false, included: false},
7 | 'node_modules/jquery/dist/jquery.min.js',
8 | 'dist/circle-progress.js',
9 | 'tests/test_utils.js',
10 | 'tests/tests.js'
11 | ],
12 | browsers: ['Firefox', 'PhantomJS'],
13 | singleRun: true
14 | });
15 | };
16 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - 6
4 | before_script:
5 | - export DISPLAY=:99.0
6 | - sh -e /etc/init.d/xvfb start
7 | addons:
8 | firefox: latest
9 | env:
10 | global:
11 | - secure: Z6oEIaybr8vkGTZZbDJJT+9wO4SjRdXq5AV1dlgrQZ0j2wSXmP6Q4HeL8jWWt6RFOZvMyNLq+X6KwWSAsIB7B8TRF1mBrX++MBKINj+oUUYAAhPU9yl8iwgvQLh3suER1OvB0BP/LdeFCZ8zSG2UPI1KRqk4ZdFKwEg0u4CSQvo=
12 | - secure: hMgJSvty/MP21BFervWR+uOzpqpXbyXtkVnI2d2126yUkJhcyc6v5cO9imbLerj+/AIhVX1jkz7yK5YuyNmC1/J0V/dem4EokT+4+N0T5OepDsDHO5z6pOS22hwzsDuMIqgwCkcuOhNQvi9KlNwbN1/OyBwIeIaIW6IQEPwG9iY=
13 |
--------------------------------------------------------------------------------
/tests/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Tests for jquery-circle-progress
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jquery-circle-progress",
3 | "version": "1.2.2",
4 | "authors": [
5 | "Rostyslav Bryzgunov "
6 | ],
7 | "description": "Plugin to draw animated circular progress bars",
8 | "license": "MIT",
9 | "main": "dist/circle-progress.js",
10 | "keywords": [
11 | "jquery",
12 | "canvas",
13 | "progress-bar"
14 | ],
15 | "homepage": "https://kottenator.github.io/jquery-circle-progress/",
16 | "ignore": [
17 | "**/.*",
18 | "node_modules",
19 | "bower_components",
20 | "tests"
21 | ],
22 | "dependencies": {
23 | "jquery": "*"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jquery-circle-progress",
3 | "version": "1.2.2",
4 | "author": "Rostyslav Bryzgunov ",
5 | "description": "Plugin to draw animated circular progress bars",
6 | "license": "MIT",
7 | "main": "dist/circle-progress.js",
8 | "keywords": [
9 | "jquery",
10 | "canvas",
11 | "progress-bar"
12 | ],
13 | "dependencies": {
14 | "jquery": "*"
15 | },
16 | "devDependencies": {
17 | "karma": "~1.2",
18 | "qunitjs": "~2.0",
19 | "karma-qunit": "~1.2",
20 | "karma-firefox-launcher": "~1.0",
21 | "karma-phantomjs-launcher": "~1.0",
22 | "karma-sauce-launcher": "~1.0",
23 | "uglify-js": "~2.7",
24 | "jsdoc": "~3.4"
25 | },
26 | "scripts": {
27 | "test": "karma start",
28 | "build-min": "uglifyjs dist/circle-progress.js -cmo dist/circle-progress.min.js --comments",
29 | "build-docs": "jsdoc dist/circle-progress.js -c jsdoc.conf"
30 | },
31 | "repository": {
32 | "type": "git",
33 | "url": "git://github.com/kottenator/jquery-circle-progress.git"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Rostyslav Bryzgunov
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/karma-saucelabs.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration
2 | module.exports = function(config) {
3 | var customLaunchers = {
4 | 'Latest Chrome on Windows 10': {
5 | base: 'SauceLabs',
6 | platform: 'Windows 10',
7 | browserName: 'chrome',
8 | version: 'latest'
9 | },
10 | 'Latest Firefox on Windows 10': {
11 | base: 'SauceLabs',
12 | platform: 'Windows 10',
13 | browserName: 'firefox',
14 | version: 'latest'
15 | },
16 | 'IE9 on Windows 7': {
17 | base: 'SauceLabs',
18 | platform: 'Windows 7',
19 | browserName: 'internet explorer',
20 | version: '9'
21 | },
22 | 'Latest Safari on OS X 10.11': {
23 | base: 'SauceLabs',
24 | platform: 'OS X 10.11',
25 | browserName: 'safari',
26 | version: 'latest'
27 | },
28 | 'iPhone emulator': {
29 | base: 'SauceLabs',
30 | platform: "OS X 10.11",
31 | browserName: 'iphone',
32 | version: "8.1"
33 | },
34 | 'Android emulator': {
35 | base: 'SauceLabs',
36 | platform: 'Linux',
37 | browserName: 'android',
38 | version: '5.0'
39 | }
40 | };
41 |
42 | config.set({
43 | frameworks: ['qunit'],
44 | files: [
45 | {pattern: 'tests/images/circle.png', served: true, watched: false, included: false},
46 | 'node_modules/jquery/dist/jquery.min.js',
47 | 'dist/circle-progress.js',
48 | 'tests/test_utils.js',
49 | 'tests/tests.js'
50 | ],
51 | sauceLabs: {
52 | testName: 'Unit tests for jquery-circle-progress'
53 | },
54 | captureTimeout: 120000,
55 | customLaunchers: customLaunchers,
56 | browsers: Object.keys(customLaunchers),
57 | reporters: ['dots', 'saucelabs'],
58 | singleRun: true
59 | });
60 | };
61 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | jquery-circle-progress - jQuery Plugin to draw animated circular progress bars
8 |
9 |
10 |
11 |
12 |
13 |
14 | jquery-circle-progress
15 |
16 |
17 |
18 |
19 | no
animation
20 |
21 |
22 |
23 |
24 | animation
progress
25 |
26 |
27 |
28 |
29 | value
progress
30 |
31 |
32 |
33 | custom angle,
value update
34 |
35 |
36 |
48 | image fill,
custom sizes
49 |
50 |
51 |
52 |
53 | See these examples code and
54 | read the documentation on GitHub
55 |
56 |
57 |
58 | Download version 1.2.2
59 | bower install jquery-circle-progress
60 | npm install jquery-circle-progress
61 |
62 |
63 |
64 | © 2014-2017 - made by Rostyslav Bryzgunov
65 |
66 |
67 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/docs/styles.css:
--------------------------------------------------------------------------------
1 | /* These are just a test styles - you don't need them in your project */
2 | body {
3 | background-color: #444;
4 | padding-top: 40px;
5 | font: 15px/1.3 Arial, sans-serif;
6 | color: #fff;
7 | text-align: center;
8 | }
9 |
10 | a {
11 | color: orange;
12 | }
13 |
14 | .new-tab-link {
15 | padding-right: 14px;
16 | background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3ggXDSIzCeRHfQAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAA9SURBVBjTY2RAA/+XMvxHF2NkwAOwacCq4P9Shv8suFQzRiNsYUEXwKoJ2VhkNrIaJgYiAAs2N2BVRMirAD6JHi10MCdVAAAAAElFTkSuQmCC) no-repeat right center;
17 | }
18 |
19 | .page-title {
20 | font: 400 40px/1.5 Open Sans, sans-serif;
21 | text-align: center;
22 | }
23 |
24 | .circles {
25 | margin-bottom: -10px;
26 | }
27 |
28 | .circle {
29 | width: 100px;
30 | margin: 6px 6px 20px;
31 | display: inline-block;
32 | position: relative;
33 | text-align: center;
34 | line-height: 1.2;
35 | }
36 |
37 | .circle canvas {
38 | vertical-align: top;
39 | }
40 |
41 | .circle strong {
42 | position: absolute;
43 | top: 30px;
44 | left: 0;
45 | width: 100%;
46 | text-align: center;
47 | line-height: 40px;
48 | font-size: 30px;
49 | }
50 |
51 | .circle strong i {
52 | font-style: normal;
53 | font-size: 0.6em;
54 | font-weight: normal;
55 | }
56 |
57 | .circle span {
58 | display: block;
59 | color: #aaa;
60 | margin-top: 12px;
61 | }
62 |
63 | p {
64 | margin: 40px 0;
65 | }
66 |
67 | .install {
68 | display: inline-block;
69 | }
70 |
71 | .install a {
72 | display: block;
73 | width: auto;
74 | vertical-align: middle;
75 | padding: 6px 12px;
76 | line-height: 20px;
77 | background-color: #111;
78 | color: #fff;
79 | border-radius: 3px;
80 | text-decoration: none;
81 | margin: 5px auto;
82 | transition: all .3s;
83 | }
84 |
85 | .install code {
86 | padding: 6px 12px;
87 | display: block;
88 | font: 13px/20px Courier New, Liberation Mono, monospase;
89 | background-color: #333333;
90 | border-radius: 4px;
91 | margin: 5px 0;
92 | white-space: nowrap;
93 | }
94 |
95 | .install a:hover {
96 | background-color: #222;
97 | }
98 |
99 | .credits {
100 | color: #aaa;
101 | position: fixed;
102 | left: 0;
103 | bottom: 0;
104 | width: 100%;
105 | }
106 |
107 | .credits img {
108 | margin-left: 4px;
109 | border-radius: 4px;
110 | vertical-align: middle;
111 | }
112 |
113 | @media (max-height: 600px), (max-width: 480px) {
114 | .credits {
115 | position: inherit;
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/docs/examples.js:
--------------------------------------------------------------------------------
1 | /* Examples */
2 | (function($) {
3 | /*
4 | * Example 1:
5 | *
6 | * - no animation
7 | * - custom gradient
8 | *
9 | * By the way - you may specify more than 2 colors for the gradient
10 | */
11 | $('.first.circle').circleProgress({
12 | value: 0.35,
13 | animation: false,
14 | fill: {gradient: ['#ff1e41', '#ff5f43']}
15 | });
16 |
17 | /*
18 | * Example 2:
19 | *
20 | * - default gradient
21 | * - listening to `circle-animation-progress` event and display the animation progress: from 0 to 100%
22 | */
23 | $('.second.circle').circleProgress({
24 | value: 0.6
25 | }).on('circle-animation-progress', function(event, progress) {
26 | $(this).find('strong').html(Math.round(100 * progress) + '%');
27 | });
28 |
29 | /*
30 | * Example 3:
31 | *
32 | * - very custom gradient
33 | * - listening to `circle-animation-progress` event and display the dynamic change of the value: from 0 to 0.8
34 | */
35 | $('.third.circle').circleProgress({
36 | value: 0.75,
37 | fill: {gradient: [['#0681c4', .5], ['#4ac5f8', .5]], gradientAngle: Math.PI / 4}
38 | }).on('circle-animation-progress', function(event, progress, stepValue) {
39 | $(this).find('strong').text(stepValue.toFixed(2).substr(1));
40 | });
41 |
42 | /*
43 | * Example 4:
44 | *
45 | * - solid color fill
46 | * - custom start angle
47 | * - custom line cap
48 | * - dynamic value set
49 | */
50 | var c4 = $('.forth.circle');
51 |
52 | c4.circleProgress({
53 | startAngle: -Math.PI / 4 * 3,
54 | value: 0.5,
55 | lineCap: 'round',
56 | fill: {color: '#ffa500'}
57 | });
58 |
59 | // Let's emulate dynamic value update
60 | setTimeout(function() { c4.circleProgress('value', 0.7); }, 1000);
61 | setTimeout(function() { c4.circleProgress('value', 1.0); }, 1100);
62 | setTimeout(function() { c4.circleProgress('value', 0.5); }, 2100);
63 |
64 | /*
65 | * Example 5:
66 | *
67 | * - image fill; image should be squared; it will be stretched to SxS size, where S - size of the widget
68 | * - fallback color fill (when image is not loaded)
69 | * - custom widget size (default is 100px)
70 | * - custom circle thickness (default is 1/14 of the size)
71 | * - reverse drawing mode
72 | * - custom animation start value
73 | * - usage of "data-" attributes
74 | */
75 | $('.fifth.circle').circleProgress({
76 | value: 0.7
77 | // all other config options were taken from "data-" attributes
78 | // options passed in config object have higher priority than "data-" attributes
79 | // "data-" attributes are taken into account only on init (not on update/redraw)
80 | // "data-fill" (and other object options) should be in valid JSON format
81 | });
82 | })(jQuery);
83 |
--------------------------------------------------------------------------------
/tests/test_utils.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | QUnit.extend(QUnit.assert, {
3 | pixelRGBA: function(canvas, x, y, expectedRGBA, message) {
4 | return _pixelColor.call(this, canvas, x, y, expectedRGBA, 0, message, _parseRGBA, _dumpRGBA);
5 | },
6 |
7 | pixelHex: function(canvas, x, y, expectedHex, message) {
8 | return _pixelColor.call(this, canvas, x, y, expectedHex, 0, message, _parseHex, _dumpHex, true);
9 | },
10 |
11 | pixelCloseRGBA: function(canvas, x, y, expectedRGBA, maxDiff, message) {
12 | if (typeof maxDiff == 'undefined' || maxDiff === null)
13 | maxDiff = 0.01;
14 | return _pixelColor.call(this, canvas, x, y, expectedRGBA, maxDiff, message, _parseRGBA, _dumpRGBA);
15 | },
16 |
17 | pixelCloseHex: function(canvas, x, y, expectedHex, maxDiff, message) {
18 | if (typeof maxDiff == 'undefined' || maxDiff === null)
19 | maxDiff = 0.015;
20 | return _pixelColor.call(this, canvas, x, y, expectedHex, maxDiff, message, _parseHex, _dumpHex, true);
21 | }
22 | });
23 |
24 | function _pixelColor(canvas, x, y, expectedColor, maxDiff, message, parseColorFn, dumpColorFn, ignoreAlpha) {
25 | var scaleBy = window.devicePixelRatio || 1,
26 | data = canvas.getContext('2d').getImageData(Math.round(x * scaleBy), Math.round(y * scaleBy), 1, 1).data,
27 | expectedData = parseColorFn(expectedColor),
28 | actualColor = dumpColorFn(data);
29 |
30 | maxDiff = maxDiff || 0;
31 |
32 | var actualDiff = Math.max(
33 | Math.abs(data[0] - expectedData[0]) / 255,
34 | Math.abs(data[1] - expectedData[1]) / 255,
35 | Math.abs(data[2] - expectedData[2]) / 255,
36 | ignoreAlpha ? 0 : Math.abs(data[3] - expectedData[3]) / 255
37 | );
38 |
39 | var result = actualDiff <= maxDiff;
40 |
41 | if (!message) {
42 | message = "Pixel color at " + x + "×" + y + " should be ";
43 | message += maxDiff ? "close to " + expectedColor : "equal to " + expectedColor;
44 | if (!result) {
45 | message += ". Actual color: " + actualColor;
46 | message += maxDiff ? ". Actual diff: " + actualDiff.toFixed(6) + ". Expected diff: " + maxDiff : "";
47 | }
48 | }
49 |
50 | this.push(result, actualColor, expectedColor, message);
51 | }
52 |
53 | function _parseRGBA(s) {
54 | s = s.replace(/^rgba\(|\s+|\)$/gi, '').split(',');
55 | return [
56 | parseInt(s[0], 10),
57 | parseInt(s[1], 10),
58 | parseInt(s[2], 10),
59 | s[3] * 255
60 | ];
61 | }
62 |
63 | function _dumpRGBA(data) {
64 | return 'rgba(' + data[0] + ', ' + data[1] + ', ' + data[2] + ', ' + data[3] / 255 + ')';
65 | }
66 |
67 | function _parseHex(s) {
68 | s = s.replace(/[#\s]/gi, '');
69 | return [
70 | parseInt(s.substr(0, 2), 16),
71 | parseInt(s.substr(2, 2), 16),
72 | parseInt(s.substr(4, 2), 16),
73 | 255
74 | ];
75 | }
76 |
77 | function _dumpHex(data) {
78 | var r = '0' + data[0].toString(16),
79 | g = '0' + data[1].toString(16),
80 | b = '0' + data[2].toString(16);
81 | r = r.substr(r.length - 2);
82 | g = g.substr(g.length - 2);
83 | b = b.substr(b.length - 2);
84 | return '#' + r + g + b;
85 | }
86 | })();
87 |
--------------------------------------------------------------------------------
/dist/circle-progress.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * jquery-circle-progress - jQuery Plugin to draw animated circular progress bars:
3 | * {@link http://kottenator.github.io/jquery-circle-progress/}
4 | *
5 | * @author Rostyslav Bryzgunov
6 | * @version 1.2.2
7 | * @licence MIT
8 | * @preserve
9 | */
10 | !function(i){if("function"==typeof define&&define.amd)define(["jquery"],i);else if("object"==typeof module&&module.exports){var t=require("jquery");i(t),module.exports=t}else i(jQuery)}(function(i){function t(i){this.init(i)}t.prototype={value:0,size:100,startAngle:-Math.PI,thickness:"auto",fill:{gradient:["#3aeabb","#fdd250"]},emptyFill:"rgba(0, 0, 0, .1)",animation:{duration:1200,easing:"circleProgressEasing"},animationStartValue:0,reverse:!1,lineCap:"butt",insertMode:"prepend",constructor:t,el:null,canvas:null,ctx:null,radius:0,arcFill:null,lastFrameValue:0,init:function(t){i.extend(this,t),this.radius=this.size/2,this.initWidget(),this.initFill(),this.draw(),this.el.trigger("circle-inited")},initWidget:function(){this.canvas||(this.canvas=i("