PluginProbe ʕ •ᴥ•ʔ
Spider Elements – Premium Elementor Widgets & Addons Library / 1.5.0
Spider Elements – Premium Elementor Widgets & Addons Library v1.5.0
trunk 1.0.0 1.1.0 1.5.0 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.7.0 1.8.0 1.9.0
spider-elements / assets / vendors / circle-progressbar / circle-progress.js
spider-elements / assets / vendors / circle-progressbar Last commit date
circle-progress.js 1 year ago circularprogress.css 1 year ago jquery.counterup.min.js 1 year ago jquery.waypoints.min.js 1 year ago
circle-progress.js
440 lines
1 /*
2 jquery-circle-progress - jQuery Plugin to draw animated circular progress bars
3
4 URL: http://kottenator.github.io/jquery-circle-progress/
5 Author: Rostyslav Bryzgunov <kottenator@gmail.com>
6 Version: 1.1.3
7 License: 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);
440