PageSourceSearch

https://springboardcreative.biz/wp-content/themes/soprano-ecommerc…/jquery.circle-progress.js?ver=6.7.10

js springboardcreative.biz collected 2026-10-09 05:20:07 UTC 17,910 bytes, 552 lines download raw bytes

vendor: 17,910 bytes, lines 1-552
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 <[email protected]>
6 * @version 1.2.2
7 * @licence MIT
8 * @preserve
9 */
10// UMD factory - https://github.com/umdjs/umd/blob/d31bb6ee7098715e019f52bdfe27b3e4bfd2b97e/templates/jqueryPlugin.js
11// Uses AMD, CommonJS or browser globals to create a jQuery plugin.
12(function(factory) {
13    if (typeof define === 'function' && define.amd) {
14        // AMD - register as an anonymous module
15        define(['jquery'], factory);
16    } else if (typeof module === 'object' && module.exports) {
17        // Node/CommonJS
18        var $ = require('jquery');
19        factory($);
20        module.exports = $;
21    } else {
22        // Browser globals
23        factory(jQuery);
24    }
25})(function($) {
26    /**
27     * Inner implementation of the circle progress bar.
28     * The class is not exposed _yet_ but you can create an instance through jQuery method call.
29     *
30     * @param {object} config - You can customize any class member (property or method).
31     * @class
32     * @alias CircleProgress
33     */
34    function CircleProgress(config) {
35        this.init(config);
36    }
37
38    CircleProgress.prototype = {
39        //--------------------------------------- public options ---------------------------------------
40        /**
41         * This is the only required option. It should be from `0.0` to `1.0`.
42         * @type {number}
43         * @default 0.0
44         */
45        value: 0.0,
46
47        /**
48         * Size of the canvas in pixels.
49         * It's a square so we need only one dimension.
50         * @type {number}
51         * @default 100.0
52         */
53        size: 100.0,
54
55        /**
56         * Initial angle for `0.0` value in radians.
57         * @type {number}
58         * @default -Math.PI
59         */
60        startAngle: -Math.PI,
61
62        /**
63         * Width of the arc in pixels.
64         * If it's `'auto'` - the value is calculated as `[this.size]{@link CircleProgress#size} / 14`.
65         * @type {number|string}
66         * @default 'auto'
67         */
68        thickness: 'auto',
69
70        /**
71         * Fill of the arc. You may set it to:
72         *
73         *   - solid color:
74         *     - `'#3aeabb'`
75         *     - `{ color: '#3aeabb' }`
76         *     - `{ color: 'rgba(255, 255, 255, .3)' }`
77         *   - linear gradient _(left to right)_:
78         *     - `{ gradient: ['#3aeabb', '#fdd250'], gradientAngle: Math.PI / 4 }`
79         *     - `{ gradient: ['red', 'green', 'blue'], gradientDirection: [x0, y0, x1, y1] }`
80         *     - `{ gradient: [["red", .2], ["green", .3], ["blue", .8]] }`
81         *   - image:
82         *     - `{ image: 'http://i.imgur.com/pT0i89v.png' }`
83         *     - `{ image: imageObject }`
84         *     - `{ color: 'lime', image: 'http://i.imgur.com/pT0i89v.png' }` -
85         *       color displayed until the image is loaded
86         *
87         * @default {gradient: ['#3aeabb', '#fdd250']}
88         */
89        fill: {
90            gradient: ['#3aeabb', '#fdd250']
91        },
92
93        /**
94         * Color of the "empty" arc. Only a color fill supported by now.
95         * @type {string}
96         * @default 'rgba(0, 0, 0, .1)'
97         */
98        emptyFill: 'rgba(0, 0, 0, .1)',
99
100        /**
101         * jQuery Animation config.
102         * You can pass `false` to disable the animation.
103         * @see http://api.jquery.com/animate/
104         * @type {object|boolean}
105         * @default {duration: 1200, easing: 'circleProgressEasing'}
106         */
107        animation: {
108            duration: 1200,
109            easing: 'circleProgressEasing'
110        },
111
112        /**
113         * Default animation starts at `0.0` and ends at specified `value`. Let's call this _direct animation_.
114         * If you want to make _reversed animation_ - set `animationStartValue: 1.0`.
115         * Also you may specify any other value from `0.0` to `1.0`.
116         * @type {number}
117         * @default 0.0
118         */
119        animationStartValue: 0.0,
120
121        /**
122         * Reverse animation and arc draw.
123         * By default, the arc is filled from `0.0` to `value`, _clockwise_.
124         * With `reverse: true` the arc is filled from `1.0` to `value`, _counter-clockwise_.
125         * @type {boolean}
126         * @default false
127         */
128        reverse: false,
129
130        /**
131         * Arc line cap: `'butt'`, `'round'` or `'square'` -
132         * [read more]{@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D.lineCap}.
133         * @type {string}
134         * @default 'butt'
135         */
136        lineCap: 'butt',
137
138        /**
139         * Canvas insertion mode: append or prepend it into the parent element?
140         * @type {string}
141         * @default 'prepend'
142         */
143        insertMode: 'prepend',
144
145        //------------------------------ protected properties and methods ------------------------------
146        /**
147         * Link to {@link CircleProgress} constructor.
148         * @protected
149         */
150        constructor: CircleProgress,
151
152        /**
153         * Container element. Should be passed into constructor config.
154         * @protected
155         * @type {jQuery}
156         */
157        el: null,
158
159        /**
160         * Canvas element. Automatically generated and prepended to [this.el]{@link CircleProgress#el}.
161         * @protected
162         * @type {HTMLCanvasElement}
163         */
164        canvas: null,
165
166        /**
167         * 2D-context of [this.canvas]{@link CircleProgress#canvas}.
168         * @protected
169         * @type {CanvasRenderingContext2D}
170         */
171        ctx: null,
172
173        /**
174         * Radius of the outer circle. Automatically calculated as `[this.size]{@link CircleProgress#size} / 2`.
175         * @protected
176         * @type {number}
177         */
178        radius: 0.0,
179
180        /**
181         * Fill of the main arc. Automatically calculated, depending on [this.fill]{@link CircleProgress#fill} option.
182         * @protected
183         * @type {string|CanvasGradient|CanvasPattern}
184         */
185        arcFill: null,
186
187        /**
188         * Last rendered frame value.
189         * @protected
190         * @type {number}
191         */
192        lastFrameValue: 0.0,
193
194        /**
195         * Init/re-init the widget.
196         *
197         * Throws a jQuery event:
198         *
199         * - `circle-inited(jqEvent)`
200         *
201         * @param {object} config - You can customize any class member (property or method).
202         */
203        init: function(config) {
204            $.extend(this, config);
205            this.radius = this.size / 2;
206            this.initWidget();
207            this.initFill();
208            this.draw();
209            this.el.trigger('circle-inited');
210        },
211
212        /**
213         * Initialize `<canvas>`.
214         * @protected
215         */
216        initWidget: function() {
217            if (!this.canvas)
218                this.canvas = $('<canvas>')[this.insertMode == 'prepend' ? 'prependTo' : 'appendTo'](this.el)[0];
219
220            var canvas = this.canvas;
221            canvas.width = this.size;
222            canvas.height = this.size;
223            this.ctx = canvas.getContext('2d');
224
225            if (window.devicePixelRatio > 1) {
226                var scaleBy = window.devicePixelRatio;
227                canvas.style.width = canvas.style.height = this.size + 'px';
228                canvas.width = canvas.height = this.size * scaleBy;
229                this.ctx.scale(scaleBy, scaleBy);
230            }
231        },
232
233        /**
234         * This method sets [this.arcFill]{@link CircleProgress#arcFill}.
235         * It could do this async (on image load).
236         * @protected
237         */
238        initFill: function() {
239            var self = this,
240                fill = this.fill,
241                ctx = this.ctx,
242                size = this.size;
243
244            if (!fill)
245                throw Error("The fill is not specified!");
246
247            if (typeof fill == 'string')
248                fill = {color: fill};
249
250            if (fill.color)
251                this.arcFill = fill.color;
252
253            if (fill.gradient) {
254                var gr = fill.gradient;
255
256                if (gr.length == 1) {
257                    this.arcFill = gr[0];
258                } else if (gr.length > 1) {
259                    var ga = fill.gradientAngle || 0, // gradient direction angle; 0 by default
260                        gd = fill.gradientDirection || [
261                                size / 2 * (1 - Math.cos(ga)), // x0
262                                size / 2 * (1 + Math.sin(ga)), // y0
263                                size / 2 * (1 + Math.cos(ga)), // x1
264                                size / 2 * (1 - Math.sin(ga))  // y1
265                            ];
266
267                    var lg = ctx.createLinearGradient.apply(ctx, gd);
268
269                    for (var i = 0; i < gr.length; i++) {
270                        var color = gr[i],
271                            pos = i / (gr.length - 1);
272
273                        if ($.isArray(color)) {
274                            pos = color[1];
275                            color = color[0];
276                        }
277
278                        lg.addColorStop(pos, color);
279                    }
280
281                    this.arcFill = lg;
282                }
283            }
284
285            if (fill.image) {
286                var img;
287
288                if (fill.image instanceof Image) {
289                    img = fill.image;
290                } else {
291                    img = new Image();
292                    img.src = fill.image;
293                }
294
295                if (img.complete)
296                    setImageFill();
297                else
298                    img.onload = setImageFill;
299            }
300
301            function setImageFill() {
302                var bg = $('<canvas>')[0];
303                bg.width = self.size;
304                bg.height = self.size;
305                bg.getContext('2d').drawImage(img, 0, 0, size, size);
306                self.arcFill = self.ctx.createPattern(bg, 'no-repeat');
307                self.drawFrame(self.lastFrameValue);
308            }
309        },
310
311        /**
312         * Draw the circle.
313         * @protected
314         */
315        draw: function() {
316            if (this.animation)
317                this.drawAnimated(this.value);
318            else
319                this.drawFrame(this.value);
320        },
321
322        /**
323         * Draw a single animation frame.
324         * @protected
325         * @param {number} v - Frame value.
326         */
327        drawFrame: function(v) {
328            this.lastFrameValue = v;
329            this.ctx.clearRect(0, 0, this.size, this.size);
330            this.drawEmptyArc(v);
331            this.drawArc(v);
332        },
333
334        /**
335         * Draw the arc (part of the circle).
336         * @protected
337         * @param {number} v - Frame value.
338         */
339        drawArc: function(v) {
340            if (v === 0)
341                return;
342
343            var ctx = this.ctx,
344                r = this.radius,
345                t = this.getThickness(),
346                a = this.startAngle;
347
348            ctx.save();
349            ctx.beginPath();
350
351            if (!this.reverse) {
352                ctx.arc(r, r, r - t / 2, a, a + Math.PI * 2 * v);
353            } else {
354                ctx.arc(r, r, r - t / 2, a - Math.PI * 2 * v, a);
355            }
356
357            ctx.lineWidth = t;
358            ctx.lineCap = this.lineCap;
359            ctx.strokeStyle = this.arcFill;
360            ctx.stroke();
361            ctx.restore();
362        },
363
364        /**
365         * Draw the _empty (background)_ arc (part of the circle).
366         * @protected
367         * @param {number} v - Frame value.
368         */
369        drawEmptyArc: function(v) {
370            var ctx = this.ctx,
371                r = this.radius,
372                t = this.getThickness(),
373                a = this.startAngle;
374
375            if (v < 1) {
376                ctx.save();
377                ctx.beginPath();
378
379                if (v <= 0) {
380                    ctx.arc(r, r, r - t / 2, 0, Math.PI * 2);
381                } else {
382                    if (!this.reverse) {
383                        ctx.arc(r, r, r - t / 2, a + Math.PI * 2 * v, a);
384                    } else {
385                        ctx.arc(r, r, r - t / 2, a, a - Math.PI * 2 * v);
386                    }
387                }
388
389                ctx.lineWidth = t;
390                ctx.strokeStyle = this.emptyFill;
391                ctx.stroke();
392                ctx.restore();
393            }
394        },
395
396        /**
397         * Animate the progress bar.
398         *
399         * Throws 3 jQuery events:
400         *
401         * - `circle-animation-start(jqEvent)`
402         * - `circle-animation-progress(jqEvent, animationProgress, stepValue)` - multiple event
403         *   animationProgress: from `0.0` to `1.0`; stepValue: from `0.0` to `value`
404         * - `circle-animation-end(jqEvent)`
405         *
406         * @protected
407         * @param {number} v - Final value.
408         */
409        drawAnimated: function(v) {
410            var self = this,
411                el = this.el,
412                canvas = $(this.canvas);
413
414            // stop previous animation before new "start" event is triggered
415            canvas.stop(true, false);
416            el.trigger('circle-animation-start');
417
418            canvas
419                .css({animationProgress: 0})
420                .animate({animationProgress: 1}, $.extend({}, this.animation, {
421                    step: function(animationProgress) {
422                        var stepValue = self.animationStartValue * (1 - animationProgress) + v * animationProgress;
423                        self.drawFrame(stepValue);
424                        el.trigger('circle-animation-progress', [animationProgress, stepValue]);
425                    }
426                }))
427                .promise()
428                .always(function() {
429                    // trigger on both successful & failure animation end
430                    el.trigger('circle-animation-end');
431                });
432        },
433
434        /**
435         * Get the circle thickness.
436         * @see CircleProgress#thickness
437         * @protected
438         * @returns {number}
439         */
440        getThickness: function() {
441            return $.isNumeric(this.thickness) ? this.thickness : this.size / 14;
442        },
443
444        /**
445         * Get current value.
446         * @protected
447         * @return {number}
448         */
449        getValue: function() {
450            return this.value;
451        },
452
453        /**
454         * Set current value (with smooth animation transition).
455         * @protected
456         * @param {number} newValue
457         */
458        setValue: function(newValue) {
459            if (this.animation)
460                this.animationStartValue = this.lastFrameValue;
461            this.value = newValue;
462            this.draw();
463        }
464    };
465
466    //----------------------------------- Initiating jQuery plugin -----------------------------------
467    $.circleProgress = {
468        // Default options (you may override them)
469        defaults: CircleProgress.prototype
470    };
471
472    // ease-in-out-cubic
473    $.easing.circleProgressEasing = function(x) {
474        if (x < 0.5) {
475            x = 2 * x;
476            return 0.5 * x * x * x;
477        } else {
478            x = 2 - 2 * x;
479            return 1 - 0.5 * x * x * x;
480        }
481    };
482
483    /**
484     * Creates an instance of {@link CircleProgress}.
485     * Produces [init event]{@link CircleProgress#init} and [animation events]{@link CircleProgress#drawAnimated}.
486     *
487     * @param {object} [configOrCommand] - Config object or command name.
488     *
489     * Config example (you can specify any {@link CircleProgress} property):
490     *
491     * ```js
492     * { value: 0.75, size: 50, animation: false }
493     * ```
494     *
495     * Commands:
496     *
497     * ```js
498     * el.circleProgress('widget'); // get the <canvas>
499     * el.circleProgress('value'); // get the value
500     * el.circleProgress('value', newValue); // update the value
501     * el.circleProgress('redraw'); // redraw the circle
502     * el.circleProgress(); // the same as 'redraw'
503     * ```
504     *
505     * @param {string} [commandArgument] - Some commands (like `'value'`) may require an argument.
506     * @see CircleProgress
507     * @alias "$(...).circleProgress"
508     */
509    $.fn.circleProgress = function(configOrCommand, commandArgument) {
510        var dataName = 'circle-progress',
511            firstInstance = this.data(dataName);
512
513        if (configOrCommand == 'widget') {
514            if (!firstInstance)
515                throw Error('Calling "widget" method on not initialized instance is forbidden');
516            return firstInstance.canvas;
517        }
518
519        if (configOrCommand == 'value') {
520            if (!firstInstance)
521                throw Error('Calling "value" method on not initialized instance is forbidden');
522            if (typeof commandArgument == 'undefined') {
523                return firstInstance.getValue();
524            } else {
525                var newValue = arguments[1];
526                return this.each(function() {
527                    $(this).data(dataName).setValue(newValue);
528                });
529            }
530        }
531
532        return this.each(function() {
533            var el = $(this),
534                instance = el.data(dataName),
535                config = $.isPlainObject(configOrCommand) ? configOrCommand : {};
536
537            if (instance) {
538                instance.init(config);
539            } else {
540                var initialConfig = $.extend({}, el.data());
541                if (typeof initialConfig.fill == 'string')
542                    initialConfig.fill = JSON.parse(initialConfig.fill);
543                if (typeof initialConfig.animation == 'string')
544                    initialConfig.animation = JSON.parse(initialConfig.animation);
545                config = $.extend(initialConfig, config);
546                config.el = el;
547                instance = new CircleProgress(config);
548                el.data(dataName, instance);
549            }
550        });
551    };
552});

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.