D3.js Dynamic Donut Chart
Pull some data and draw a donut and a table
by k_sav
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
<div class="c-donut js-donut" data-donut-data='[{"fund":"AUSTRALIAN sHaRes","rate":17,"range":"10-20"},{"fund":"international shares","rate":22,"range":"20-30"},{"fund":"direct property","rate":8,"range":"5-10"},{"fund":"infrastructure","rate":6,"range":"2-10"},{"fund":"private equity","rate":1.5,"range":"1-5"},{"fund":"credit","rate":12,"range":"10-15"},{"fund":"fixed interest","rate":22,"range":"15-25"},{"fund":"cash","rate":11.5,"range":"10-15"},{"fund":"other assets","rate":0,"range":"0-2"}]'>
<h4 class="c-donut-header">Investment breakdown</h4>
<div class="row">
<div class="col-md-4 offset-md-1 js-donut-holder">
</div>
<div class="col-md-6 offset-md-1 js-legend-holder"></div>
</div>
</div>
CSS
html {
font-size: 62.5%;
}
body {
margin: 0;
padding: 0;
width: 100%;
font-size: 1.6rem;
}
svg {
width: 100%;
}
.c-tooltip {
width: 9rem;
position: absolute;
padding: 1rem;
font: 12px sans-serif;
border: 1px solid #616161;
border-radius: .8rem;
pointer-events: none;
z-index: 10;
background: white;
line-height: 1.4;
margin-top: -2.3rem;
margin-left: 2rem;
}
.c-tooltip--right {
margin-left: -13rem;
}
.c-tooltip-color {
display: inline-block;
vertical-align: baseline;
width: .4rem;
height: 1.2rem;
margin-right: .3rem;
}
.tip {
width: 0;
height: 0;
position: absolute;
left: -2rem;
top: 1.1rem;
border: solid 1rem;
border-color: transparent #616161 transparent transparent;
}
.c-tooltip--right .tip {
left: auto;
right: -2rem;
border-color: transparent transparent transparent #616161;
}
.tip:after {
content: ' ';
width: 0;
height: 0;
position: absolute;
left: -9px;
top: -10px;
border: solid 10px;
border-color: transparent #fff transparent transparent;
}
.c-tooltip--right .tip:after {
left: auto;
right: -.9rem;
border-color: transparent transparent transparent #fff;
}
.c-tooltip p {
margin: 0;
}
.c-donut__legend-color {
display: inline-block;
width: 2rem;
height: 2rem;
margin-right: 1rem;
border-radius: 50%;
}
.c-donut__legend-item:hover {
cursor: default;
}
.c-donut__legend-item--highlight {
background: #eee;
}
JavaScript
const CLASSES = {
COMPONENT: 'js-donut',
legend: 'c-donut__legend',
donutGroup: 'c-donut__group',
donutArc: 'c-donut__arc',
legendItem: 'c-donut__legend-item',
legendItemHighlight: 'c-donut__legend-item--highlight',
legendColor: 'c-donut__legend-color',
tooltip: 'c-tooltip',
tooltipTip: 'tip',
tooltipRight: 'c-tooltip--right',
tooltipColor: 'c-tooltip-color',
}
const SELECTORS = {
COMPONENT: `.${CLASSES.COMPONENT}`,
donutArc: `.${CLASSES.arc}`,
legendHolder: '.js-legend-holder',
donutHolder: '.js-donut-holder',
}
const SETTINGS = {
margin: {
top: 0,
right: 0,
bottom: 0,
left: 0,
},
breakpoints: {
mobile: 320,
tablet: 740,
},
colors: {
bg: '#ffffff',
funds: {
'australian-shares': '#ef7f00',
'international-shares': '#d0d0ce',
'cash': '#bc032a',
'direct-property': '#00a4e7',
'infrastructure': '#f36205',
'private-equity': '#c9520d',
'credit': '#e1edfa',
'fixed-interest': '#c0dbf3',
'other-assets': '#f14432',
},
},
arc: {
outerRadius: 0.99,
innerRadius: 0.65,
},
}
function getWindowWidth() {
const width = document.getElementsByClassName(CLASSES.COMPONENT)[0].clientWidth
return width
}
function getRadius() {
return getWindowWidth() / 2
}
function isMobileVersion() {
if (getWindowWidth() < SETTINGS.breakpoints.tablet) {
//console.log('is mobile')
return true
}
//console.log('is not mobile')
return false
}
// Calculate arcs
const arc = d3.svg.arc()
.outerRadius(getRadius() * SETTINGS.arc.outerRadius)
.innerRadius(getRadius() * SETTINGS.arc.innerRadius)
// Calculate donut
const cookDonut = d3.layout.pie()
.sort(null)
.value(function(d) {
return d.rate;
})
// Define our main component div
const component = d3.select(SELECTORS.COMPONENT)
// Define SVG element, append to col1
const svg = d3.select(SELECTORS.donutHolder).append('svg')
.attr('preserveAspectRatio', 'xMinYMin')
// Define...