263 lines
8.8 KiB
JavaScript
263 lines
8.8 KiB
JavaScript
|
"use strict";
|
||
|
|
||
|
(function ($) {
|
||
|
|
||
|
$.fn.circliful = function (options, callback) {
|
||
|
|
||
|
var settings = $.extend({
|
||
|
// These are the defaults.
|
||
|
startdegree: 0,
|
||
|
fgcolor: "#556b2f",
|
||
|
bgcolor: "#eee",
|
||
|
fill: false,
|
||
|
width: 15,
|
||
|
dimension: 200,
|
||
|
fontsize: 15,
|
||
|
percent: 50,
|
||
|
animationstep: 1.0,
|
||
|
iconsize: '20px',
|
||
|
iconcolor: '#999',
|
||
|
border: 'default',
|
||
|
complete: null,
|
||
|
bordersize: 10
|
||
|
}, options);
|
||
|
|
||
|
return this.each(function () {
|
||
|
|
||
|
var customSettings = ["fgcolor", "bgcolor", "fill", "width", "dimension", "fontsize", "animationstep", "endPercent", "icon", "iconcolor", "iconsize", "border", "startdegree", "bordersize"];
|
||
|
|
||
|
var customSettingsObj = {};
|
||
|
var icon = '';
|
||
|
var percent;
|
||
|
var endPercent = 0;
|
||
|
var obj = $(this);
|
||
|
var fill = false;
|
||
|
var text, info;
|
||
|
|
||
|
obj.addClass('circliful');
|
||
|
|
||
|
checkDataAttributes(obj);
|
||
|
|
||
|
if (obj.data('text') != undefined) {
|
||
|
text = obj.data('text');
|
||
|
|
||
|
if (obj.data('icon') != undefined) {
|
||
|
icon = $('<i></i>')
|
||
|
.addClass('fa ' + $(this).data('icon'))
|
||
|
.css({
|
||
|
'color': customSettingsObj.iconcolor,
|
||
|
'font-size': customSettingsObj.iconsize
|
||
|
});
|
||
|
}
|
||
|
|
||
|
if (obj.data('type') != undefined) {
|
||
|
type = $(this).data('type');
|
||
|
|
||
|
if (type == 'half') {
|
||
|
addCircleText(obj, 'circle-text-half', (customSettingsObj.dimension / 1.45));
|
||
|
} else {
|
||
|
addCircleText(obj, 'circle-text', customSettingsObj.dimension);
|
||
|
}
|
||
|
} else {
|
||
|
addCircleText(obj, 'circle-text', customSettingsObj.dimension);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($(this).data("total") != undefined && $(this).data("part") != undefined) {
|
||
|
var total = $(this).data("total") / 100;
|
||
|
|
||
|
percent = (($(this).data("part") / total) / 100).toFixed(3);
|
||
|
endPercent = ($(this).data("part") / total).toFixed(3);
|
||
|
} else {
|
||
|
if ($(this).data("percent") != undefined) {
|
||
|
percent = $(this).data("percent") / 100;
|
||
|
endPercent = $(this).data("percent");
|
||
|
} else {
|
||
|
percent = settings.percent / 100;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($(this).data('info') != undefined) {
|
||
|
info = $(this).data('info');
|
||
|
|
||
|
if ($(this).data('type') != undefined) {
|
||
|
type = $(this).data('type');
|
||
|
|
||
|
if (type == 'half') {
|
||
|
addInfoText(obj, 0.9);
|
||
|
} else {
|
||
|
addInfoText(obj, 1.25);
|
||
|
}
|
||
|
} else {
|
||
|
addInfoText(obj, 1.25);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$(this).width(customSettingsObj.dimension + 'px');
|
||
|
|
||
|
var size = customSettingsObj.dimension,
|
||
|
canvas = $('<canvas></canvas>').attr({
|
||
|
width: size,
|
||
|
height: size
|
||
|
}).appendTo($(this)).get(0);
|
||
|
|
||
|
var context = canvas.getContext('2d');
|
||
|
|
||
|
var dpr = window.devicePixelRatio;
|
||
|
if ( dpr ) {
|
||
|
var $canvas = $(canvas);
|
||
|
$canvas.css('width', size);
|
||
|
$canvas.css('height', size);
|
||
|
$canvas.attr('width', size * dpr);
|
||
|
$canvas.attr('height', size * dpr);
|
||
|
|
||
|
context.scale(dpr, dpr);
|
||
|
}
|
||
|
|
||
|
var container = $(canvas).parent();
|
||
|
var x = size / 2;
|
||
|
var y = size / 2;
|
||
|
var degrees = customSettingsObj.percent * 360.0;
|
||
|
var radians = degrees * (Math.PI / 180);
|
||
|
var radius = size / 2.5;
|
||
|
var startAngle = 2.3 * Math.PI;
|
||
|
var endAngle = 0;
|
||
|
var counterClockwise = false;
|
||
|
var curPerc = customSettingsObj.animationstep === 0.0 ? endPercent : 0.0;
|
||
|
var curStep = Math.max(customSettingsObj.animationstep, 0.0);
|
||
|
var circ = Math.PI * 2;
|
||
|
var quart = Math.PI / 2;
|
||
|
var type = '';
|
||
|
var fireCallback = true;
|
||
|
var additionalAngelPI = (customSettingsObj.startdegree / 180) * Math.PI;
|
||
|
|
||
|
if ($(this).data('type') != undefined) {
|
||
|
type = $(this).data('type');
|
||
|
|
||
|
if (type == 'half') {
|
||
|
startAngle = 2.0 * Math.PI;
|
||
|
endAngle = 3.13;
|
||
|
circ = Math.PI;
|
||
|
quart = Math.PI / 0.996;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($(this).data('type') != undefined) {
|
||
|
type = $(this).data('type');
|
||
|
|
||
|
if (type == 'angle') {
|
||
|
startAngle = 2.25 * Math.PI;
|
||
|
endAngle = 2.4;
|
||
|
circ = 1.53 + Math.PI;
|
||
|
quart = 0.73 + Math.PI / 0.996;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* adds text to circle
|
||
|
*
|
||
|
* @param obj
|
||
|
* @param cssClass
|
||
|
* @param lineHeight
|
||
|
*/
|
||
|
function addCircleText(obj, cssClass, lineHeight) {
|
||
|
$("<span></span>")
|
||
|
.appendTo(obj)
|
||
|
.addClass(cssClass)
|
||
|
.html(text)
|
||
|
.prepend(icon)
|
||
|
.css({
|
||
|
'line-height': lineHeight + 'px',
|
||
|
'font-size': customSettingsObj.fontsize + 'px'
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* adds info text to circle
|
||
|
*
|
||
|
* @param obj
|
||
|
* @param factor
|
||
|
*/
|
||
|
function addInfoText(obj, factor) {
|
||
|
$('<span></span>')
|
||
|
.appendTo(obj)
|
||
|
.addClass('circle-info-half')
|
||
|
.css(
|
||
|
'line-height', (customSettingsObj.dimension * factor) + 'px'
|
||
|
)
|
||
|
.text(info);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* checks which data attributes are defined
|
||
|
* @param obj
|
||
|
*/
|
||
|
function checkDataAttributes(obj) {
|
||
|
$.each(customSettings, function (index, attribute) {
|
||
|
if (obj.data(attribute) != undefined) {
|
||
|
customSettingsObj[attribute] = obj.data(attribute);
|
||
|
} else {
|
||
|
customSettingsObj[attribute] = $(settings).attr(attribute);
|
||
|
}
|
||
|
|
||
|
if (attribute == 'fill' && obj.data('fill') != undefined) {
|
||
|
fill = true;
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* animate foreground circle
|
||
|
* @param current
|
||
|
*/
|
||
|
function animate(current) {
|
||
|
|
||
|
context.clearRect(0, 0, canvas.width, canvas.height);
|
||
|
|
||
|
context.beginPath();
|
||
|
context.arc(x, y, radius, endAngle, startAngle, false);
|
||
|
|
||
|
context.lineWidth = customSettingsObj.width + 1;
|
||
|
|
||
|
context.strokeStyle = customSettingsObj.bgcolor;
|
||
|
context.stroke();
|
||
|
|
||
|
if (fill) {
|
||
|
context.fillStyle = customSettingsObj.fill;
|
||
|
context.fill();
|
||
|
}
|
||
|
|
||
|
context.beginPath();
|
||
|
context.arc(x, y, radius, -(quart) + additionalAngelPI, ((circ) * current) - quart + additionalAngelPI, false);
|
||
|
|
||
|
if (customSettingsObj.border == 'outline') {
|
||
|
context.lineWidth = customSettingsObj.width + customSettingsObj.bordersize;
|
||
|
} else if (customSettingsObj.border == 'inline') {
|
||
|
context.lineWidth = customSettingsObj.width - customSettingsObj.bordersize;
|
||
|
}
|
||
|
|
||
|
context.strokeStyle = customSettingsObj.fgcolor;
|
||
|
context.stroke();
|
||
|
|
||
|
if (curPerc < endPercent) {
|
||
|
curPerc += curStep;
|
||
|
requestAnimationFrame(function () {
|
||
|
animate(Math.min(curPerc, endPercent) / 100);
|
||
|
}, obj);
|
||
|
}
|
||
|
|
||
|
if (curPerc == endPercent && fireCallback && typeof(options) != "undefined") {
|
||
|
if ($.isFunction(options.complete)) {
|
||
|
options.complete();
|
||
|
|
||
|
fireCallback = false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
animate(curPerc / 100);
|
||
|
|
||
|
});
|
||
|
};
|
||
|
}(jQuery));
|