Skip to content

Instantly share code, notes, and snippets.

@brianbancroft
Forked from mbostock/.block
Last active November 17, 2016 20:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brianbancroft/0ba0fb59fd9e84355570a0b8d3ecc844 to your computer and use it in GitHub Desktop.
Save brianbancroft/0ba0fb59fd9e84355570a0b8d3ecc844 to your computer and use it in GitHub Desktop.
D3 JS Object Line Chart with ToolTips
license: gpl-3.0

This little fork is a modification from Mike Bostock's Basic Line Chart series. The aim here is that instead of pulling data from a .tsv, I'm pulling it from an old-school JS object, which is the format I'm going to be dealing with more often than not.

<!DOCTYPE html>
<meta charset="utf-8">
<style>
.axis--x path {
display: none;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
div.tooltip {
position: absolute;
text-align: center;
width: 60px;
height: 28px;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
</style>
<svg width="500" height="400"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
let data = [
{x:"Jan-2015", y:267968},
{x:"Feb-2015", y:268318},
{x:"Mar-2015", y:268624},
{x:"Apr-2015", y:268833},
{x:"May-2015", y:269155},
{x:"Jun-2015", y:268498},
{x:"Jul-2015", y:267899},
{x:"Aug-2015", y:267876},
{x:"Sep-2015", y:268040},
{x:"Oct-2015", y:268166},
{x:"Nov-2015", y:268010},
{x:"Dec-2015", y:268782}
]
function moneyWithCommas(x) {
return '$' + x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
}
let svg = d3.select('svg'),
margin = {top: 20, right: 20, bottom: 30, left: 50},
width = +svg.attr('width') - margin.left - margin.right,
height = +svg.attr('height') - margin.top - margin.bottom,
g = svg.append('g').attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')')
let parseTime = d3.timeParse('%b-%Y')
let x = d3.scaleTime()
.rangeRound([0, width])
let y = d3.scaleLinear()
.domain([
d3.min(data, d => d.y - 2000),
d3.max(data, d => d.y + 2000)
])
.rangeRound([height, 0])
let div = d3.select('body').append('div')
.attr('class', 'tooltip')
.style('opacity', 0)
let line = d3.line()
.x(function(d) { return x(parseTime(d.x)) })
.y(function(d) { return y(d.y) })
x.domain(d3.extent(data, function(d) { return parseTime(d.x); }))
g.append('g')
.attr('class', 'axis axis--x')
.attr('transform', 'translate(0, ' + height + ')')
.call(d3.axisBottom(x)
.tickFormat(d3.timeFormat('%b-%Y'))
.ticks(d3.timeMonth.every(3))
)
g.append('g')
.attr('class', 'axis axis--y')
.call(d3.axisLeft(y)
.ticks(4)
)
.append('text')
.attr('fill', '#000')
.attr('transform', 'rotate(-90)')
.attr('y', 6)
.attr('dy', '0.71em')
.style('text-anchor', 'end')
.text('Price ($, CAD)')
g.append('path')
.datum(data)
.attr('class', 'line')
.attr('d', line)
// Add the scatterplot
g.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("r", 4)
.attr('stroke', '#414141')
.attr('fill', 'steelblue')
.attr("cx", function(d) { return x(parseTime(d.x)); })
.attr("cy", function(d) { return y(d.y); })
.on('mouseover', d => {
//console.log('mouseover event')
div.transition().duration(250).style('opacity', 0.9)
div.html(d.x + "<br/>" + moneyWithCommas(d.y))
.style('left', (d3.event.pageX) + 'px')
.style('top', (d3.event.pageY) + 'px')
})
.on('mouseout', d => {
//console.log('mouseout event')
div.transition()
.duration(500)
.style('opacity', 0)
})
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment