Progress pie chart
Show 0-100% as a clock face progression with basic CSS animation
by codeplug
HTML
<input id="percent" type="number" min="0" max="100" value="35" step="5" />
<input id="size" type="number" min="16" max="1000" value="100" step="10" />
<select id="state">
<option>none</option>
<option>info</option>
<option>success</option>
<option>warning</option>
<option>danger</option>
</select>
<div id="pie">;llll
</div>
CSS
/* Create a clipped round hole for the pie chart */
.pie-wrapper {
width: 250px;
height: 250px;
position: relative;
background: white;
border-radius: 50%;
overflow: hidden;
border: 1px solid #eee;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
/* Create a half circle that animates transisions around the centre of the circle */
.pie-wrapper > .pie {
width: 50%;
height: 100%;
border-radius: 125px 0 0 125px;
position: absolute;
background: #eee;
border: 1px solid #eee;
border-right: none;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
/* Ensure that transitions rotate around the centre of the complete circle, not the centre of the div */
-moz-transform-origin: right center;
-ms-transform-origin: right center;
-o-transform-origin: right center;
-webkit-transform-origin: right center;
transform-origin: right center;
/* Animate the rotation */
-moz-transition: transform .6s linear;
-o-transition: transform .6s linear;
-webkit-transition: transform .6s linear;
transition: transform .6s linear;
}
/* .pie-filler sits behind and tracks 0-180deg */
.pie-wrapper > .pie.pie-filler {
}
/* .pie-amount sits in front and tracks 0-360deg */
.pie-wrapper > .pie.pie-amount {
}
/* .pie-mask hides the .pie sections as they rotate 0-180deg */
.pie-wrapper > .pie-mask {
width: 50%;
height: 50%;
position: absolute;
opacity: 1;
background: inherit;
-moz-transition: transform .6s ease;
-o-transition: transform .6s ease;
-webkit-transition: transform .6s ease;
transition: transform .6s ease;
}
/* .pie-mask.q3 rotates out of view 0-180deg */
.pie-wrapper > .pie-mask.q3 {
top: 50%;
border-radius: 0 0 0 125px;
-moz-transform-origin: right top;
-ms-transform-origin: right top;
-o-transform-origin: right top;
-webkit-transform-origin: right top;
transform-origin: right top;
}
/* .pie-mask.q4...
JavaScript
(function ($) {
'use strict';
var timers = {};
var transformSupported = false;
function rotateIncrementPie($pie, deg) {
/// <summary>Increment the pie by up to 90deg towards the value.</summary>
/// <param name="$pie" type="jQuery">The pie jQuery object.</param>
/// <param name="deg" type="Number">The degrees to rotate 0-360.</param>
var incrementKey = $pie.attr('id') || 'default';
window.clearTimeout(timers[incrementKey]);
var current = $pie.data('deg');
var difference = Math.abs(deg - current);
if (difference > 90) {
// The panels glitch when CSS animated more than 90deg in one go - there isn't enough time to hide the masks as the amount semicircle rotates in
// Set a timeout so that after the current animation finishes it tries again
var original = deg;
timers[incrementKey] = window.setTimeout(function () {
rotateIncrementPie($pie, original);
}, 600);
// Adjust the value we're going to set so that it is within 90deg of the current
deg = deg > current ? current + 90 : current - 90
}
rotatePie($pie, deg);
}
function rotatePie($pie, deg) {
/// <summary>Rotate the panels in the pie to represent the value.</summary>
/// <param name="$pie" type="jQuery">The pie jQuery object.</param>
/// <param name="deg" type="Number">The degrees to rotate 0-360.</param>
// Set a data value we can get back easily
var current = $pie.data('deg');
$pie.data('deg', deg);
// Rotate the amount pie half by the degs
$pie.find('.pie-amount').css('transform', 'rotate(' + deg + 'deg)');
if (deg < 90) {
// If less than 90 masks are needed for q3 and q4 to hide the .pie-amount
$pie.find('.pie-mask.q3').show().css('transform', 'rotate(0deg)');
$pie.find('.pie-mask.q4').show();
// If less than 180 then rotate the .pie-filler with the .pie-amount
$pie.find('.pie-filler').css('transform', 'rotate(' + deg + 'deg)');
}
else {
if (deg < 180) {
// If less than 180 but more than 90 then rotate q3...