PluginProbe ʕ •ᴥ•ʔ
10Web Booster – Website speed optimization, Cache & Page Speed optimizer / trunk
10Web Booster – Website speed optimization, Cache & Page Speed optimizer vtrunk
2.33.0 2.30.5 2.30.7 2.30.9 2.31.10 2.31.8 2.32.11 2.32.21 2.32.3 2.32.4 2.32.7 2.6.31 2.6.40 2.6.42 2.6.7 2.7.37 2.7.44 2.7.47 2.8.18 2.8.19 2.8.32 2.8.34 2.8.35 2.9.23 2.9.24 2.9.25 2.9.27 v2.27.4 trunk 2.0.10 2.0.11 2.0.12 2.0.13 2.0.14 2.0.15 2.0.17 2.0.18 2.0.21 2.0.22 2.0.25 2.0.26 2.0.27 2.0.3 2.0.7 2.0.9 2.10.46 2.10.65 2.10.66 2.10.68 2.11.41 2.11.42 2.11.43 2.12.15 2.12.21 2.12.22 2.12.23 2.12.26 2.13.37 2.13.40 2.13.41 2.13.42 2.13.44 2.13.45 2.13.47 2.14.49 2.14.50 2.15.18 2.17.21 2.17.23 2.18.17 2.19.44 2.19.45 2.19.46 2.19.49 2.2.12 2.2.15 2.2.16 2.2.18 2.2.8 2.20.31 2.20.32 2.20.33 2.21.11 2.21.12 2.21.16 2.21.25 2.22.32 2.23.13 2.23.15 2.23.16 2.23.18 2.24.12 2.24.14 2.24.18 2.25.14 2.26.6 2.28.10 2.28.13 2.28.14 2.28.7 2.29.1 2.29.2 2.29.3 2.3.0 2.3.1 2.3.2 2.3.3 2.30.18
tenweb-speed-optimizer / assets / js / circle-progress.js
tenweb-speed-optimizer / assets / js Last commit date
gutenberg 3 years ago gutenbergComponents 3 years ago autoupdate_banner.js 3 years ago banner_main.js 3 years ago circle-progress.js 3 years ago datatables.min.js 4 years ago jquery.multi-select.js 4 years ago jquery.tagsinput.min.js 4 years ago referral_program.js 3 years ago sidebar-plugin.js 3 years ago speed.js 3 years ago two_admin.js 1 year ago two_admin_bar.js 4 years ago two_bf_countdown.js 3 years ago two_deactivate_plugin.js 3 years ago two_elementor_editor.js 2 years ago two_preview.js 3 years ago two_update_white_label.js 1 year ago two_white_label.js 2 years ago
circle-progress.js
553 lines
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 <kottenator@gmail.com>
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 });
553