Skip to content

Instantly share code, notes, and snippets.

@oguzhaneren
Created August 5, 2015 11:59
Show Gist options
  • Save oguzhaneren/bf116799a50493a457b2 to your computer and use it in GitHub Desktop.
Save oguzhaneren/bf116799a50493a457b2 to your computer and use it in GitHub Desktop.
Knockout binding for circle progress
ko.bindingHandlers.progressCircle = {
update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
var $element = $(element),
opt = ko.unwrap(valueAccessor());
var options = $.extend( {}, {
showText:true,
size:48,
thickness:3,
value:100
}, opt );
$(element).progressCircle({
nPercent : ko.unwrap(options.value),
showPercentText : options.showText,
thickness :options.thickness,
circleSize : options.size
});
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
});
}
};
/****************************************************************
*
* CSS Percentage Circle
* Based on CSS provided by Andre Firchow
*
*****************************************************************/
.prog-circle .slice {
position : absolute;
width : 1em;
height : 1em;
clip : rect(0em, 1em, 1em, 0.5em);
}
.prog-circle .slice.clipauto {
clip : rect(auto, auto, auto, auto);
}
.prog-circle .fill, .prog-circle .bar {
position : absolute;
border : 0.08em solid #90c844;
width : 0.84em;
height : 0.84em;
clip : rect(0em, .5em, 1em, 0em);
-webkit-border-radius : 50%;
-moz-border-radius : 50%;
-ms-border-radius : 50%;
-o-border-radius : 50%;
border-radius : 50%;
-webkit-transform : rotate(20deg);
-moz-transform : rotate(20deg);
-ms-transform : rotate(20deg);
-o-transform : rotate(20deg);
transform : rotate(20deg);
}
.prog-circle {
position : relative;
font-size : 120px;
width : 1em;
height : 1em;
-webkit-border-radius : 50%;
-moz-border-radius : 50%;
-ms-border-radius : 50%;
-o-border-radius : 50%;
border-radius : 50%;
float : left;
margin : 0 0.1em 0.1em 0;
background-color : #e6f2b6;
}
.prog-circle .percenttext {
position : absolute;
width : 100%;
height : 1em;
z-index : 1;
margin : auto;
top : 0;
left : 0;
right : 0;
bottom : 0;
font-size : 0.3em;
color : #90c844;
display : block;
text-align : center;
white-space : nowrap;
line-height : 100%;
-webkit-transition-duration : 0.2s;
-moz-transition-duration : 0.2s;
-o-transition-duration : 0.2s;
transition-duration : 0.2s;
-webkit-transition-timing-function : ease-out;
-moz-transition-timing-function : ease-out;
-o-transition-timing-function : ease-out;
transition-timing-function : ease-out;
}
.prog-circle .after {
position : absolute;
top : 0.08em;
left : 0.08em;
display : block;
content : " ";
-webkit-border-radius : 50%;
-moz-border-radius : 50%;
-ms-border-radius : 50%;
-o-border-radius : 50%;
border-radius : 50%;
background-color : #FFFFFF;
width : 0.84em;
height : 0.84em;
}
( function( $ ){
var ProgressCircle = function( element, options ){
var settings = $.extend( {}, $.fn.progressCircle.defaults, options );
var thicknessConstant = 0.02;
var nRadian = 0;
computePercent();
setThickness();
var border = ( settings.thickness * thicknessConstant ) + 'em';
var offset = ( 1 - thicknessConstant * settings.thickness * 2 ) + 'em';
var circle = $( element );
var progCirc = circle.find( '.prog-circle' );
var circleDiv = progCirc.find( '.bar' );
var circleSpan = progCirc.children( '.percenttext' );
var circleFill = progCirc.find( '.fill' );
var circleSlice = progCirc.find( '.slice' );
if ( settings.nPercent == 0 ) {
circleSlice.hide();
} else {
resetCircle();
transformCircle( nRadians, circleDiv );
}
setBorderThickness();
updatePercentage();
setCircleSize();
function computePercent () {
settings.nPercent > 100 || settings.nPercent < 0 ? settings.nPercent = 0 : settings.nPercent;
nRadians = ( 360 * settings.nPercent ) / 100;
}
function setThickness () {
if ( settings.thickness > 10 ) {
settings.thickness = 10;
} else if ( settings.thickness < 1 ) {
settings.thickness = 1;
} else {
settings.thickness = Math.round( settings.thickness );
}
}
function setCircleSize ( ) {
progCirc.css( 'font-size', settings.circleSize + 'px' );
}
function transformCircle ( nRadians, cDiv ) {
var rotate = "rotate(" + nRadians + "deg)";
cDiv.css({
"-webkit-transform" : rotate,
"-moz-transform" : rotate,
"-ms-transform" : rotate,
"-o-transform" : rotate,
"transform" : rotate
});
if( nRadians > 180 ) {
transformCircle( 180, circleFill );
circleSlice.addClass( ' clipauto ');
}
}
function setBorderThickness () {
progCirc.find(' .slice > div ').css({
'border-width' : border,
'width' : offset,
'height' : offset
})
progCirc.find('.after').css({
'top' : border,
'left' : border,
'width' : offset,
'height' : offset
})
}
function resetCircle () {
circleSlice.show();
circleSpan.text( '' );
circleSlice.removeClass( 'clipauto' )
transformCircle( 20, circleDiv );
transformCircle( 20, circleFill );
return this;
}
function updatePercentage () {
settings.showPercentText && circleSpan.text( settings.nPercent + '%' );
}
};
$.fn.progressCircle = function( options ) {
return this.each( function( key, value ){
var element = $( this );
if ( element.data( 'progressCircle' ) ) {
var progressCircle = new ProgressCircle( this, options );
return element.data( 'progressCircle' );
}
$( this ).append( '<div class="prog-circle">' +
' <div class="percenttext"> </div>' +
' <div class="slice">' +
' <div class="bar"> </div>' +
' <div class="fill"> </div>' +
' </div>' +
' <div class="after"> </div>' +
'</div>');
var progressCircle = new ProgressCircle( this, options );
element.data( 'progressCircle', progressCircle );
});
};
$.fn.progressCircle.defaults = {
nPercent : 50,
showPercentText : true,
circleSize : 100,
thickness : 3
};
})( jQuery );
<div data-bind="progressCircle: {value:20}"></div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment