PageSourceSearch

https://3nerds.net/wp-content/themes/truesoft-pro/assets/vendors/js/circle-progress.js?ver=7.1.2

js 3nerds.net collected 2026-10-01 03:53:23 UTC 14,238 bytes, 439 lines download raw bytes

vendor: 14,238 bytes, lines 1-439
1/*
2jquery-circle-progress - jQuery Plugin to draw animated circular progress bars
3
4URL: http://kottenator.github.io/jquery-circle-progress/
5Author: Rostyslav Bryzgunov <[email protected]>
6Version: 1.1.3
7License: MIT
8*/
9(function($) {
10    function CircleProgress(config) {
11        this.init(config);
12    }
13
14    CircleProgress.prototype = {
15        //----------------------------------------------- public options -----------------------------------------------
16        /**
17         * This is the only required option. It should be from 0.0 to 1.0
18         * @type {number}
19         */
20        value: 0.0,
21
22        /**
23         * Size of the circle / canvas in pixels
24         * @type {number}
25         */
26        size: 100.0,
27
28        /**
29         * Initial angle for 0.0 value in radians
30         * @type {number}
31         */
32        startAngle: -Math.PI,
33
34        /**
35         * Width of the arc. By default it's auto-calculated as 1/14 of size, but you may set it explicitly in pixels
36         * @type {number|string}
37         */
38        thickness: 'auto',
39
40        /**
41         * Fill of the arc. You may set it to:
42         *   - solid color:
43         *     - { color: '#3aeabb' }
44         *     - { color: 'rgba(255, 255, 255, .3)' }
45         *   - linear gradient (left to right):
46         *     - { gradient: ['#3aeabb', '#fdd250'], gradientAngle: Math.PI / 4 }
47         *     - { gradient: ['red', 'green', 'blue'], gradientDirection: [x0, y0, x1, y1] }
48         *   - image:
49         *     - { image: 'http://i.imgur.com/pT0i89v.png' }
50         *     - { image: imageObject }
51         *     - { color: 'lime', image: 'http://i.imgur.com/pT0i89v.png' } - color displayed until the image is loaded
52         */
53        fill: {
54            gradient: ['#3aeabb', '#fdd250']
55        },
56
57        /**
58         * Color of the "empty" arc. Only a color fill supported by now
59         * @type {string}
60         */
61        emptyFill: 'rgba(0, 0, 0, .1)',
62
63        /**
64         * Animation config (see jQuery animations: http://api.jquery.com/animate/)
65         */
66        animation: {
67            duration: 1200,
68            easing: 'circleProgressEasing'
69        },
70
71        /**
72         * Default animation starts at 0.0 and ends at specified `value`. Let's call this direct animation.
73         * If you want to make reversed animation then you should set `animationStartValue` to 1.0.
74         * Also you may specify any other value from 0.0 to 1.0
75         * @type {number}
76         */
77        animationStartValue: 0.0,
78
79        /**
80         * Reverse animation and arc draw
81         * @type {boolean}
82         */
83        reverse: false,
84
85        /**
86         * Arc line cap ('butt', 'round' or 'square')
87         * Read more: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D.lineCap
88         * @type {string}
89         */
90        lineCap: 'butt',
91
92        //-------------------------------------- protected properties and methods --------------------------------------
93        /**
94         * @protected
95         */
96        constructor: CircleProgress,
97
98        /**
99         * Container element. Should be passed into constructor config
100         * @protected
101         * @type {jQuery}
102         */
103        el: null,
104
105        /**
106         * Canvas element. Automatically generated and prepended to the {@link CircleProgress.el container}
107         * @protected
108         * @type {HTMLCanvasElement}
109         */
110        canvas: null,
111
112        /**
113         * 2D-context of the {@link CircleProgress.canvas canvas}
114         * @protected
115         * @type {CanvasRenderingContext2D}
116         */
117        ctx: null,
118
119        /**
120         * Radius of the outer circle. Automatically calculated as {@link CircleProgress.size} / 2
121         * @protected
122         * @type {number}
123         */
124        radius: 0.0,
125
126        /**
127         * Fill of the main arc. Automatically calculated, depending on {@link CircleProgress.fill} option
128         * @protected
129         * @type {string|CanvasGradient|CanvasPattern}
130         */
131        arcFill: null,
132
133        /**
134         * Last rendered frame value
135         * @protected
136         * @type {number}
137         */
138        lastFrameValue: 0.0,
139
140        /**
141         * Init/re-init the widget
142         * @param {object} config - Config
143         */
144        init: function(config) {
145            $.extend(this, config);
146            this.radius = this.size / 2;
147            this.initWidget();
148            this.initFill();
149            this.draw();
150        },
151
152        /**
153         * @protected
154         */
155        initWidget: function() {
156            var canvas = this.canvas = this.canvas || $('<canvas>').prependTo(this.el)[0];
157            canvas.width = this.size;
158            canvas.height = this.size;
159            this.ctx = canvas.getContext('2d');
160        },
161
162        /**
163         * This method sets {@link CircleProgress.arcFill}
164         * It could do this async (on image load)
165         * @protected
166         */
167        initFill: function() {
168            var self = this,
169                fill = this.fill,
170                ctx = this.ctx,
171                size = this.size;
172
173            if (!fill)
174                throw Error("The fill is not specified!");
175
176            if (fill.color)
177                this.arcFill = fill.color;
178
179            if (fill.gradient) {
180                var gr = fill.gradient;
181
182                if (gr.length == 1) {
183                    this.arcFill = gr[0];
184                } else if (gr.length > 1) {
185                    var ga = fill.gradientAngle || 0, // gradient direction angle; 0 by default
186                        gd = fill.gradientDirection || [
187                            size / 2 * (1 - Math.cos(ga)), // x0
188                            size / 2 * (1 + Math.sin(ga)), // y0
189                            size / 2 * (1 + Math.cos(ga)), // x1
190                            size / 2 * (1 - Math.sin(ga))  // y1
191                        ];
192
193                    var lg = ctx.createLinearGradient.apply(ctx, gd);
194
195                    for (var i = 0; i < gr.length; i++) {
196                        var color = gr[i],
197                            pos = i / (gr.length - 1);
198
199                        if ($.isArray(color)) {
200                            pos = color[1];
201                            color = color[0];
202                        }
203
204                        lg.addColorStop(pos, color);
205                    }
206
207                    this.arcFill = lg;
208                }
209            }
210
211            if (fill.image) {
212                var img;
213
214                if (fill.image instanceof Image) {
215                    img = fill.image;
216                } else {
217                    img = new Image();
218                    img.src = fill.image;
219                }
220
221                if (img.complete)
222                    setImageFill();
223                else
224                    img.onload = setImageFill;
225            }
226
227            function setImageFill() {
228                var bg = $('<canvas>')[0];
229                bg.width = self.size;
230                bg.height = self.size;
231                bg.getContext('2d').drawImage(img, 0, 0, size, size);
232                self.arcFill = self.ctx.createPattern(bg, 'no-repeat');
233                self.drawFrame(self.lastFrameValue);
234            }
235        },
236
237        draw: function() {
238            if (this.animation)
239                this.drawAnimated(this.value);
240            else
241                this.drawFrame(this.value);
242        },
243
244        /**
245         * @protected
246         * @param {number} v - Frame value
247         */
248        drawFrame: function(v) {
249            this.lastFrameValue = v;
250            this.ctx.clearRect(0, 0, this.size, this.size);
251            this.drawEmptyArc(v);
252            this.drawArc(v);
253        },
254
255        /**
256         * @protected
257         * @param {number} v - Frame value
258         */
259        drawArc: function(v) {
260            var ctx = this.ctx,
261                r = this.radius,
262                t = this.getThickness(),
263                a = this.startAngle;
264
265            ctx.save();
266            ctx.beginPath();
267
268            if (!this.reverse) {
269                ctx.arc(r, r, r - t / 2, a, a + Math.PI * 2 * v);
270            } else {
271                ctx.arc(r, r, r - t / 2, a - Math.PI * 2 * v, a);
272            }
273
274            ctx.lineWidth = t;
275            ctx.lineCap = this.lineCap;
276            ctx.strokeStyle = this.arcFill;
277            ctx.stroke();
278            ctx.restore();
279        },
280
281        /**
282         * @protected
283         * @param {number} v - Frame value
284         */
285        drawEmptyArc: function(v) {
286            var ctx = this.ctx,
287                r = this.radius,
288                t = this.getThickness(),
289                a = this.startAngle;
290
291            if (v < 1) {
292                ctx.save();
293                ctx.beginPath();
294
295                if (v <= 0) {
296                    ctx.arc(r, r, r - t / 2, 0, Math.PI * 2);
297                } else {
298                    if (!this.reverse) {
299                        ctx.arc(r, r, r - t / 2, a + Math.PI * 2 * v, a);
300                    } else {
301                        ctx.arc(r, r, r - t / 2, a, a - Math.PI * 2 * v);
302                    }
303                }
304
305                ctx.lineWidth = t;
306                ctx.strokeStyle = this.emptyFill;
307                ctx.stroke();
308                ctx.restore();
309            }
310        },
311
312        /**
313         * @protected
314         * @param {number} v - Value
315         */
316        drawAnimated: function(v) {
317            var self = this,
318                el = this.el,
319                canvas = $(this.canvas);
320
321            // stop previous animation before new "start" event is triggered
322            canvas.stop(true, false);
323            el.trigger('circle-animation-start');
324
325            canvas
326                .css({ animationProgress: 0 })
327                .animate({ animationProgress: 1 }, $.extend({}, this.animation, {
328                    step: function (animationProgress) {
329                        var stepValue = self.animationStartValue * (1 - animationProgress) + v * animationProgress;
330                        self.drawFrame(stepValue);
331                        el.trigger('circle-animation-progress', [animationProgress, stepValue]);
332                    }
333                }))
334                .promise()
335                .always(function() {
336                    // trigger on both successful & failure animation end
337                    el.trigger('circle-animation-end');
338                });
339        },
340
341        /**
342         * @protected
343         * @returns {number}
344         */
345        getThickness: function() {
346            return $.isNumeric(this.thickness) ? this.thickness : this.size / 14;
347        },
348
349        getValue: function() {
350            return this.value;
351        },
352
353        setValue: function(newValue) {
354            if (this.animation)
355                this.animationStartValue = this.lastFrameValue;
356            this.value = newValue;
357            this.draw();
358        }
359    };
360
361    //-------------------------------------------- Initiating jQuery plugin --------------------------------------------
362    $.circleProgress = {
363        // Default options (you may override them)
364        defaults: CircleProgress.prototype
365    };
366
367    // ease-in-out-cubic
368    $.easing.circleProgressEasing = function(x, t, b, c, d) {
369        if ((t /= d / 2) < 1)
370            return c / 2 * t * t * t + b;
371        return c / 2 * ((t -= 2) * t * t + 2) + b;
372    };
373
374    /**
375     * Draw animated circular progress bar.
376     *
377     * Appends <canvas> to the element or updates already appended one.
378     *
379     * If animated, throws 3 events:
380     *
381     *   - circle-animation-start(jqEvent)
382     *   - circle-animation-progress(jqEvent, animationProgress, stepValue) - multiple event;
383     *                                                                        animationProgress: from 0.0 to 1.0;
384     *                                                                        stepValue: from 0.0 to value
385     *   - circle-animation-end(jqEvent)
386     *
387     * @param configOrCommand - Config object or command name
388     *     Example: { value: 0.75, size: 50, animation: false };
389     *     you may set any public property (see above);
390     *     `animation` may be set to false;
391     *     you may use .circleProgress('widget') to get the canvas
392     *     you may use .circleProgress('value', newValue) to dynamically update the value
393     *
394     * @param commandArgument - Some commands (like 'value') may require an argument
395     */
396    $.fn.circleProgress = function(configOrCommand, commandArgument) {
397        var dataName = 'circle-progress',
398            firstInstance = this.data(dataName);
399
400        if (configOrCommand == 'widget') {
401            if (!firstInstance)
402                throw Error('Calling "widget" method on not initialized instance is forbidden');
403            return firstInstance.canvas;
404        }
405
406        if (configOrCommand == 'value') {
407            if (!firstInstance)
408                throw Error('Calling "value" method on not initialized instance is forbidden');
409            if (typeof commandArgument == 'undefined') {
410                return firstInstance.getValue();
411            } else {
412                var newValue = arguments[1];
413                return this.each(function() {
414                    $(this).data(dataName).setValue(newValue);
415                });
416            }
417        }
418
419        return this.each(function() {
420            var el = $(this),
421                instance = el.data(dataName),
422                config = $.isPlainObject(configOrCommand) ? configOrCommand : {};
423
424            if (instance) {
425                instance.init(config);
426            } else {
427                var initialConfig = $.extend({}, el.data());
428                if (typeof initialConfig.fill == 'string')
429                    initialConfig.fill = JSON.parse(initialConfig.fill);
430                if (typeof initialConfig.animation == 'string')
431                    initialConfig.animation = JSON.parse(initialConfig.animation);
432                config = $.extend(initialConfig, config);
433                config.el = el;
434                instance = new CircleProgress(config);
435                el.data(dataName, instance);
436            }
437        });
438    };
439})(jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.