Skip to content

Instantly share code, notes, and snippets.

@jwilber
Last active October 8, 2018 05:59
Show Gist options
  • Save jwilber/28a02d1a0bd85a596342a905ad0287be to your computer and use it in GitHub Desktop.
Save jwilber/28a02d1a0bd85a596342a905ad0287be to your computer and use it in GitHub Desktop.
interpolated line-chart with legend
license: mit

Simple interpolated line-chart with legend and mouseover.

Built with blockbuilder.org

<!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; }
g.tick line {
opacity: .1;
}
path.domain {
opacity:0;
}
</style>
</head>
<body>
<script src="linechart.js"></script>
</body>
'use strict'
d3.csv('tweetdata.csv', linechart);
function linechart(data) {
console.log(data);
const colDict = {retweets: 'skyblue', favorites: 'coral' , tweets: 'olive'}
const margin = {top: 50, right: 25, bottom: 25, left: 25};
const width = 700 - margin.right - margin.left;
const height = 500 - margin.top - margin.bottom;
const svg = d3.select('body').append('svg')
.attr('width', width + margin.right + margin.left)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
// define scales
const xScale = d3.scaleLinear().domain([1, 10]).range([20, width]);
const yScale = d3.scaleLinear().domain([0, 35]).range([height, 20]);
// define axes
const xAxis = d3.axisBottom()
.scale(xScale)
.tickSize(height + 5)
.tickValues([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
const yAxis = d3.axisRight()
.scale(yScale)
.tickSize(width + 10)
.ticks(10);
// draw axies
svg.append('g').attr('id', 'xAxisG').call(xAxis);
svg.append('g').attr('id', 'yAxisG').call(yAxis);
// Add circles
svg.selectAll('circle.tweets')
.data(data)
.enter()
.append('circle')
.attr('class', 'tweets')
.attr('r', 5)
.attr('cx', d => xScale(d.day))
.attr('cy', d => yScale(d.tweets))
.style('fill', 'olive');
svg.selectAll('circle.favorites')
.data(data)
.enter()
.append('circle')
.attr('class', 'favorites')
.attr('r', 5)
.attr('cx', d => xScale(d.day))
.attr('cy', d => yScale(d.favorites))
.style('fill', 'coral');
svg.selectAll('circle.retweets')
.data(data)
.enter()
.append('circle')
.attr('class', 'retweets')
.attr('r', 5)
.attr('cx', d => xScale(d.day))
.attr('cy', d => yScale(d.retweets))
.style('fill', 'skyblue');
// add lines
const tweetLine = d3.line()
.x(d => xScale(d.day))
.y(d => yScale(d.tweets))
.curve(d3.curveBasis);
svg.append('path')
.attr('class', 'tweets')
.attr('d', tweetLine(data))
.attr('fill', 'none')
.attr('stroke', 'olive')
.attr('stroke-width', 5)
const favoriteLine = d3.line()
.x(d => xScale(d.day))
.y(d => yScale(d.favorites))
.curve(d3.curveCardinal);
svg.append('path')
.attr('class', 'favorites')
.attr('d', favoriteLine(data))
.attr('fill', 'none')
.attr('stroke', 'coral')
.attr('stroke-width', 5)
const retweetLine = d3.line()
.x(d => xScale(d.day))
.y(d => yScale(d.retweets))
.curve(d3.curveStep);
svg.select('path')
.attr('class', 'retweets')
.attr('d', retweetLine(data))
.attr('fill', 'none')
.attr('stroke', 'skyblue')
.attr('stroke-width', 5)
// interactivity
d3.selectAll('path')
.on('mouseover', highlightLine);
d3.selectAll('path')
.on('mouseout', deHighlightLine);
function highlightLine(d) {
let col = d3.select(this).attr('stroke');
let sw = d3.select(this).attr('stroke-width');
d3.select(this).attr('stroke', d3.rgb(col).brighter(.2));
d3.select(this).attr('stroke-width', 10);
};
function deHighlightLine(d) {
let col = d3.select(this).attr('class');
let sw = d3.select(this).attr('stroke-width');
d3.select(this).attr('stroke', colDict[col]);
d3.select(this).attr('stroke-width', 5);
};
// legend
var legend_keys = ["retweets", "favorites", "tweets"]
var lineLegend = svg.selectAll(".lineLegend").data(legend_keys)
.enter().append("g")
.attr("class","lineLegend")
.attr("transform", function (d,i) {
return "translate(" + (margin.left) + "," + (i*20)+")";
});
lineLegend.append("text").text(function (d) {return d;})
.attr("transform", "translate(15, 6)"); //align texts with boxes
lineLegend.append("rect")
.attr("fill", d => colDict[d])
.attr("width", 12).attr('height', 5);
// title
d3.select('svg')
.append('text')
.html('Tweets Line-Chart')
.attr('x', width / 2 - margin.right)
.attr('y', margin.top / 2)
.attr('font', 'Georgia')
.style('font-size', 20);
};
day tweets retweets favorites
1 1 2 5
2 6 11 3
3 3 8 1
4 5 14 6
5 10 29 16
6 4 22 10
7 3 14 1
8 5 18 7
9 1 30 22
10 4 16 15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment