pie chart
using css transforms, with javascript automation
by theoperatore
HTML
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<div class="container">
<div class="row">
<div class="col-xs-12 col-md-4">
<div class="panel panel-default">
<div class="panel-body">
<h4>Dragon</h4>
<div class="progress">
<div class="progress-bar progress-bar-success" style="width: 100%">64 hp</div>
</div>
<div class="ability-chart-container">
<div class="ability-chart-mount"></div>
<div class="row ability-chart-list">
<div class="col-xs-2 ability-str">
<p>STR</p>
<p>5</p>
</div>
<div class="col-xs-2 ability-dex">
<p>DEX</p>
<p>3</p>
</div>
<div class="col-xs-2 ability-con">
<p>CON</p>
<p>5</p>
</div>
<div class="col-xs-2 ability-int">
<p>INT</p>
<p>4</p>
</div>
<div class="col-xs-2 ability-wis">
<p>WIS</p>
<p>4</p>
</div>
<div class="col-xs-2 ability-cha">
<p>CHA</p>
<p>3</p>
</div>
</div>
<hr />
<div class="row ability-chart-list">
<div class="col-xs-2">
<p>CLASS</p>
...
CSS
body, .panel-body {
background-color: #222;
color: #fff;
}
.ability-chart-container {
position: relative;
}
.ability-chart-list {
font-size: 85%;
font-family: monospace;
text-align: center;
}
.ability-chart-icon {
display:inline-block;
width: 10px;
height:10px;
background-color: #fbadd2;
margin-right: 5px;
}
.ability-chart {
width: 200px;
height: 200px;
/* background-color: #222;*/
margin: auto;
position:relative;
margin-bottom: 15px;
}
.ability-chart>.slice {
position:absolute;
display: block;
height: 100px;
width: 200px;
overflow:hidden;
-webkit-transform-origin: 100px 100px;
transform-origin: 100px 100px;
transition: all 300ms;
}
.slice>.slice-child {
position:absolute;
display:block;
content:" ";
height: 100px;
width: 200px;
-webkit-transform-origin: 100px 100px;
transform-origin: 100px 100px;
-webkit-border-top-radius: 100px;
-webkit-border-left-radius: 100px;
border-top-right-radius: 100px;
border-top-left-radius: 100px;
transition: all 300ms;
/* this is a 70 deg piece */
/*transform: rotate(110deg);*/
}
.slice-dead {
background-color: #222;
}
/* The positive rotation is the angle size
* sums of the previous pieces plus the size of
* this piece
.ability-chart>.slice:nth-of-type(2) {
transform: rotate(10deg);
}
/* The angle to rotate by is 180 - wanted degree
.ability-chart>.slice:nth-of-type(2)>.slice-child {
background-color: orange;
transform: rotate(170deg);
}
.ability-chart>.slice:nth-of-type(3) {
transform: rotate(100deg);
}
.ability-chart>.slice:nth-of-type(3)>.slice-child {
background-color: blue;
transform: rotate(90deg);
}
.ability-chart>.slice:nth-of-type(4) {
transform: rotate(130deg);
}
.ability-chart>.slice:nth-of-type(4)>.slice-child {
background-color: brown;
transform: rotate(150deg);
}
.ability-chart>.slice:nth-of-type(5) {
...
JavaScript
var mount = document.querySelector('.ability-chart-mount');
var colors = ['#fbadd2', 'blue', 'orange', 'green', 'brown', 'red'];
// array of abil mods: str, dex, con, int, wis, cha
//var data = [ 4, 2, 1, 1, 3, 5 ];
//var data = [ 19, 14, 12, 13, 16, 20 ];
var data = [5, 3, 5, 4, 4, 3];
var sum = data.reduce(function (sum, val) {
return sum + Math.abs(val);
}, 0);
var out = document.createElement('div');
out.classList.add('ability-chart');
var total = 0;
data.forEach(function (val, i) {
var slice = document.createElement('span');
var child = document.createElement('span');
var deg = Math.ceil((Math.abs(val) / sum) * 360);
total += deg;
slice.classList.add('slice');
child.classList.add('slice-child');
if (val < 0) {
child.classList.add('slice-dead');
} else {
child.style.backgroundColor = colors[i];
}
slice.style.webkitTransform = "rotate(" + total + "deg)";
slice.style.MozTransform = "rotate(" + total + "deg)";
slice.style.msTransform = "rotate(" + total + "deg)";
slice.style.OTransform = "rotate(" + total + "deg)";
slice.style.transform = "rotate(" + total + "deg)";
child.style.webkitTransform = "rotate(" + (180 - deg) + "deg)";
child.style.MozTransform = "rotate(" + (180 - deg) + "deg)";
child.style.msTransform = "rotate(" + (180 - deg) + "deg)";
child.style.OTransform = "rotate(" + (180 - deg) + "deg)";
child.style.transform = "rotate(" + (180 - deg) + "deg)";
slice.appendChild(child);
out.appendChild(slice);
});
mount.appendChild(out);