body {
padding: 1rem 3%;
}
.bx--graph-header {
font-weight: 300;
font-size: 24px;
}
.overlay {
fill: #3d70b2;
opacity: .1;
display: none;
pointer-events: none;
}
.line {
stroke-width: 2;
stroke: #FF00FF;
fill: none;
pointer-events: none;
}
.axis path {
stroke: #5A6872;
}
.tick line {
stroke: #5A6872;
}
.tick text {
fill: #5A6872;
}
.graph-container {
position: relative;
}
.tooltip {
font-weight: 700;
padding-left: 1rem 2rem;
background-color: #fff;
position: absolute;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, .1);
border: 1px solid #DFE3E6;
padding: .25rem .5rem;
pointer-events: none;
display: none;
&:after {
content: '';
top: 100%;
left: 50%;
transform: translateX(-50%);
position: absolute;
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 5px solid #fff;
}
}
.y path {
display: none;
}
.label {
font-size: 10px;
font-weight: 700;
fill: #5A6872;
text-anchor: middle;
}
View Compiled
// Function to create random data in format: [date, amount]
function createData(num) {
let data = [];
for (var i = 0; i < num; i++) {
const randomNum = Math.floor(Math.random() * 1000 + 1);
let d = new Date();
d.setDate(d.getDate() - (i * 30));
data.push({
date: d,
amount: randomNum
});
}
return data;
}
// Create + Format data
let data = createData(12).sort(function(a, b) { return a.date - b.date; });
// what are these and are they things that someone should edit
const margin = { top: 30, right: 20, bottom: 60, left: 65 };
const width = 800 - (margin.left + margin.right);
const height = 300 - (margin.top + margin.bottom);
const labelOffset = 50;
const axisOffset = 16;
// Set Time Format (JAN, FEB, etc..)
const timeFormat = d3.timeFormat('%b');
// Set the scales
const x = d3.scaleBand()
.rangeRound([0, width])
.domain(data.map((d) => d.date))
.padding(0.5);
const y = d3.scaleLinear()
.range([height, 0])
.domain([0, d3.max(data, (d) => d.amount)]);
// // Set the axes
const xAxis = d3.axisBottom()
.scale(x)
.tickSize(0)
.tickFormat(timeFormat)
const yAxis = d3.axisLeft()
.ticks(4)
.tickSize(-width)
.scale(y.nice());
// // Set up SVG with initial transform to avoid repeat positioning
const svg = d3.select('svg')
.attr('class', 'graph')
.attr('width', width + (margin.left + margin.right))
.attr('height', height + (margin.top + margin.bottom))
.append('g')
.attr('class', 'group-container')
.attr('transform', `translate(${margin.left}, ${margin.top})`)
.attr('font-family', 'ibm-plex-sans');
// // Add Y axis
svg.append('g')
.attr('class', 'axis y')
.attr('stroke-dasharray', '4')
.call(yAxis)
.selectAll('text')
.attr("x", -axisOffset)
.attr('font-family', 'ibm-plex-sans');
// // Add Y axis label
const yLabel = svg.select('.y')
.append('text')
.text('USAGE ($)')
.attr('class', 'label')
.attr('transform', `translate(${-labelOffset}, ${height / 2}) rotate(-90)`)
.attr('font-family', 'ibm-plex-sans');
// // Add X axis
svg.append('g')
.attr('class', 'axis x')
.attr('transform', `translate(0, ${height})`)
.call(xAxis)
.selectAll('text')
.attr("y", axisOffset)
.attr('font-family', 'ibm-plex-sans')
// // Add X axis label
const xLabel = svg.select('.x')
.append('text')
.text('MONTH')
.attr('class', 'label')
.attr('transform', `translate(${width / 2}, ${labelOffset})`)
.attr('font-family', 'ibm-plex-sans');
svg.append('g')
.attr('class', 'bar-container')
.selectAll('rect')
.data(data)
.enter().append('rect')
.attr('class', 'bar')
.attr('x', (d) => x(d.date))
.attr('y', (d) => height)
.attr('height', 0)
.attr('width', x.bandwidth())
.attr('fill', '#00A78F')
.transition()
.duration(500)
.delay((d, i) => i * 50)
.attr('height', (d) => height - y(d.amount))
.attr('y', (d) => y(d.amount));
// Select Tooltip
const tooltip = d3.select('.tooltip');
const bars = svg.selectAll('.bar')
.on('mouseover', function(d) {
let color = d3.color('#00A78F').darker()
d3.select(this)
.attr('fill', color)
tooltip
.style('display', 'inherit')
.text(`$${d.amount}`)
.style('top', `${y(d.amount) - axisOffset}px`);
let bandwidth = x.bandwidth();
let tooltipWidth = tooltip.nodes()[0].getBoundingClientRect().width;
let offset = (tooltipWidth - bandwidth) / 2;
tooltip
.style('left', `${x(d.date) + margin.left - offset}px`)
})
.on('mouseout', function(d) {
d3.select(this)
.transition()
.duration(250)
.attr('fill', '#00A78F')
tooltip
.style('display', 'none')
})
View Compiled