Skip to content

Instantly share code, notes, and snippets.

@dharwadravi
Created December 9, 2017 13:13
Show Gist options
  • Save dharwadravi/35d0d8abf67e78e602aa3d430160258f to your computer and use it in GitHub Desktop.
Save dharwadravi/35d0d8abf67e78e602aa3d430160258f to your computer and use it in GitHub Desktop.
bar chart from json array
license: mit
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
#card_analytics__requests_by_period {
max-width: 100%;
background: #f7f7f7;
height: 300px;
display: flex;
justify-content: center;
align-items: center;
overflow-x: auto;
}
</style>
</head>
<body>
<div id="card_analytics__requests_by_period"></div>
<script>
// DATA
var data = [
{
data_month: "2017-01-31",
label: "January",
requests_submitted: {
current: 21,
prior: 16,
during:236
}
}, {
data_month: "2017-02-28",
label: "February",
requests_submitted: {
current: 16,
prior: 43
}
}, {
data_month: "2017-03-31",
label: "March",
requests_submitted: {
current: 36,
prior: 20
}
}, {
data_month: "2017-04-30",
label: "April",
requests_submitted: {
current: 230,
prior: 310
}
}, {
data_month: "2017-05-31",
label: "May",
requests_submitted: {
current: 50,
prior: 14
}
}, {
data_month: "2017-06-30",
label: "June",
requests_submitted: {
current: 39,
prior: 47
}
}, {
data_month: "2017-07-31",
label: "July",
requests_submitted: {
current: 72,
prior: 68
}
}, {
data_month: "2017-08-31",
label: "August",
requests_submitted: {
current: 31,
prior: 97
}
}, {
data_month: "2017-09-30",
label: "September",
requests_submitted: {
current: 57,
prior: 25
}
}, {
data_month: "2017-10-31",
label: "October",
requests_submitted: {
current: 71,
prior: 45
}
}, {
data_month: "2017-11-30",
label: "November",
requests_submitted: {
current: 25,
prior: 32
}
}, {
data_month: "2017-12-31",
label: "December",
requests_submitted: {
current: 41,
prior: 21
}
}]
// VARS
/* margin object for parent container */
var margin = {top: 20, right: 20, bottom: 20, left: 40};
/* parent container id */
var container = '#card_analytics__requests_by_period'
/* width of parent container that will by dynamic in ReloQuest app. For now it is static */
var parentWidth = 900
var parentHeight = 300
/* width and height of the chart area. This is defined so that margins aren't needed in later calculations */
var width = parentWidth - margin.left - margin.right
var height = parentHeight - margin.top - margin.bottom
/* Will be used to separate each month's data into current and prior periods */
var keys = Object.keys(data[0].requests_submitted)
// SVG
/* the svg element's width and height is identical to the parent width and height. Instead of just using the `width`
and `height` variables declared earlier, we are basically setting some padding on the entire svg element so calculations
don't need to take it into account */
var svg = d3.select(container).append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
/* The g element will be where the chart actually lives */
var g = svg.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
// Scales
/* Scales the months */
var x0 = d3.scaleBand()
.domain(data.map( d => d.label))
.range([0, width])
.padding(0.2)
/* Scales the current and prior periods in each month */
var x1 = d3.scaleBand()
.domain(keys)
.range([0, x0.bandwidth()])
.padding(0.1)
/* Scales the y axis based on request values */
var y = d3.scaleLinear()
.domain([0, getRequestMax()])
.range([height, 0])
function _buildChart() {
var chart = g.append('g')
.classed('chart', true)
// Adds a `g` element for every month,
// which will contain 2 `rects` for data of each period
var months = chart.selectAll('g')
.data(data)
.enter().append('g')
.attr('transform', function(d) {
return 'translate(' + x0(d.label) + ', 0)';
})
.selectAll('rect')
.data(function(d) {
var datum = keys.map(function(key, i) {
return {
key: key,
fill: getFill(i),
val: d.requests_submitted[key]
}
});
return datum
})
.enter().append('rect')
.attr('x', d => x1(d.key))
.attr('y', d => y(d.val))
.attr('width', x1.bandwidth())
.attr('height', d => height - y(d.val))
.attr('fill', d => d.fill)
}
function _buildAxes() {
var xAxis = d3.axisBottom(x0)
var yAxis = d3.axisLeft(y)
g.append('g')
.classed('axis', true)
.attr('transform', 'translate(0,' + height +')')
.call(xAxis)
g.append('g')
.classed('axis', true)
.attr('transform', 'translate(0, 0)')
.call(yAxis)
}
function init() {
_buildChart()
_buildAxes()
}
init()
// HELPERS
/*
* Takes an index of 0 or 1 returns a color depending on the index
* @returns {string} - A color string
*/
function getFill(i) {
return i ? 'lightblue' : 'lightgreen'
}
/*
* A wrapper around the d3.max method that returns the highest request submission
* total for a given month from 2 separate years
* ---
* @returns {num}
*/
function getRequestMax() {
return d3.max(getAllRequests(data))
}
/*
* Combines all request submission values into an array
* ---
* @param {Array} `data` - An array of objects for each month
* @returns {Array}
*/
function getAllRequests(data) {
return data.reduce(function(collection, d) {
return collection.concat(
keys.map(function(key) {
return d.requests_submitted[key]
})
)
}, [])
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment