Last active
May 29, 2020 23:58
-
-
Save satirama/102e981563164e36136ac1f891522e6d to your computer and use it in GitHub Desktop.
Vertical scatter-ish chart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | |
<meta http-equiv="Content-Language" content="en-us" /> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
<title>Vertical Plot</title> | |
<meta name="author" content="Angelica Miranda - https://satirama.github.io" /> | |
<style> | |
#home { | |
width: 100%; | |
height: 100vh; | |
font-family: Arial, Helvetica, sans-serif; | |
} | |
#chart { | |
width: 100%; | |
height: 100%; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="home"> | |
<p id="tooltip"></p> | |
<div id="chart"></div> | |
</div> | |
</body> | |
<script src="https://d3js.org/d3.v5.min.js"></script> | |
<script> | |
/* | |
What have the rock & alternative bands of the Rolling Stone top 100 albums in the 2000 been up to in the last decade. | |
New LP or EP but no live sessions or live albums | |
Radiohead | |
Interpol | |
The Strokes | |
Arctic Monkeys | |
Franz Ferdinand | |
The Black Keys | |
Phoenix | |
Arcade Fire | |
Beck | |
MGMT | |
LCD Soundsystem | |
Wilco | |
The Flaming Lips | |
Yeah Yeah Yeahs | |
PJ Harvey | |
Tv on the radio | |
My Morning Jacket | |
No new albums: | |
The White Stripes | |
System of a Down | |
*/ | |
var artistsColor = { | |
"Radiohead": "#1f77b4", | |
"Interpol": "#ff7f0e", | |
"The Strokes": "#2ca02c", | |
"Arctic Monkeys": "#d62728", | |
"Franz Ferdinand": "#9467bd", | |
"The Black Keys": "#8c564b", | |
"Phoenix": "#e377c2", | |
"Arcade Fire": "#7f7f7f", | |
"Beck": "#bcbd22", | |
"MGMT": "#17becf", | |
"LCD Soundsystem": "#7fc97f", | |
"Wilco": "#beaed4", | |
"The Flaming Lips": "#fdc086", | |
"Yeah Yeah Yeahs": "#ffff99", | |
"PJ Harvey": "#386cb0", | |
"TV on the Radio": "#f0027f", | |
"My Morning Jacket": "#bf5b17" | |
} | |
function drawChart(data) { | |
const margin = { | |
top: 50, | |
right: 50, | |
bottom: 50, | |
left: 50 | |
}; | |
const years = Object.keys(data); | |
const svgWidth = document.getElementById('chart').clientWidth; | |
const svgHeight = document.getElementById('chart').clientHeight; | |
const chartWidth = svgWidth - margin.right - margin.left; | |
const chartHeight = svgHeight - margin.top - margin.bottom; | |
const paddingX = chartWidth / (years.length - 1); | |
const startY = chartHeight; | |
const paddingY = window.innerHeight / 14; // y spacing between circles, should be optimized for each case by the max number of items within a year | |
const radius = chartWidth > 500 ? 6 : 4; | |
const largeRadius = 80; | |
const svg | |
= d3.select("#chart") | |
.append("svg") | |
.attr("width", svgWidth) | |
.attr("height", svgHeight); | |
const g | |
= svg.append("g") | |
.attr("transform",`translate(${margin.left},${margin.top})`); | |
const line | |
= g.selectAll('.line') | |
.data(years) | |
.enter() | |
.append('g') | |
.attr('id', d => 'year-' + d); | |
line.append('line') | |
.attr('x1', (d, i) => i * paddingX) | |
.attr('y1', 0) | |
.attr('x2', (d, i) => i * paddingX) | |
.attr('y2', chartHeight) | |
.attr('year', d => d) | |
// accent lines every 5 years | |
.attr('stroke-width', d => d % 5 == 0 ? 2 : 1) | |
.attr('stroke', d => d % 5 == 0 ? '#b8b8b8' : '#e6e6e6'); | |
line.append('text') | |
.attr('x', d => chartHeight * -0.3 ) | |
.attr('y', function (d, i) { return parseInt(d3.select(this.parentNode).select('line').attr('x1')) - radius * 2; }) | |
.attr("text-anchor","end") | |
.attr("dominant-baseline","baseline") | |
.style("font-size", 18) | |
.attr('transform', "rotate(-90)") | |
// add labels every 5 years | |
.text(d => d % 5 == 0 ? d : ''); | |
d3.selection.prototype.moveToFront = function() { | |
return this.each(function(){ | |
this.parentNode.appendChild(this); | |
}); | |
}; | |
const circles = g.selectAll('.circles') | |
.data(years) | |
.enter() | |
.append('g') | |
.attr('class', 'circles') | |
.attr('data-year', d => d); | |
circles.selectAll('circle') | |
.data(d => {data[d].year = d; return data[d]}) | |
.enter() | |
.append('circle') | |
.attr('class', 'circle') | |
.attr('cx', function (d) { | |
const year = this.parentNode.dataset.year; | |
return d3.select('#year-' + year).select('line').attr('x1'); | |
}) | |
.attr('cy', function (d, i) { | |
const year = this.parentNode.dataset.year; | |
const qtyPerYear = data[year].length; | |
const spacing = i * paddingY; | |
const centered = (chartHeight - (qtyPerYear - 1) * paddingY )/ 2; | |
return spacing + centered; | |
}) | |
.attr('r', radius) | |
.attr('fill', d => artistsColor[d.artist]) | |
.on("mouseover", function(d, i) { | |
d3.select(this).moveToFront(); | |
d3.select(this.parentNode).moveToFront(); | |
d3.select(this) | |
.attr('cx', () => { | |
// fix position if large circle would go outside of svg | |
if (d3.select(this).attr('cx') < largeRadius) return largeRadius - 10; | |
if (Number.parseFloat(d3.select(this).attr('cx')) + largeRadius > chartWidth) return (chartWidth - largeRadius + 10); | |
return d3.select(this).attr('cx'); | |
}) | |
.attr('r', largeRadius) | |
.attr("class", "circle active") | |
.style('cursor','pointer'); | |
const tooltip = d3.select(this.parentNode) | |
.append("text") | |
.attr('id', () => "t" + i) | |
.attr('x', () => d3.select(this).attr('cx') - 52) | |
.attr('y', () => d3.select(this).attr('cy') - 24) | |
.style('fill','white') | |
.style('font-size','13px') | |
.style('font-weight', '700') | |
.style('pointer-events','none') | |
.text(() => d.artist); | |
}) | |
.on("mouseout", function(d, i) { | |
d3.select("#t" + i) | |
.transition() | |
.duration(50) | |
.remove(); | |
d3.select(this) | |
.transition() | |
.duration(200) | |
.attr('r', radius) | |
.attr('cx', function (d) { | |
const year = this.parentNode.dataset.year; | |
return d3.select('#year-' + year).select('line').attr('x1'); | |
}) | |
.style('cursor', null); | |
}); | |
} | |
getData = async () => await d3.json('musicData.json'); | |
drawChart(getData()); | |
</script> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"2010": [ | |
{ | |
"artist": "Interpol", | |
"album": "Try it on" | |
}, | |
{ | |
"artist": "The Strokes", | |
"album": "Angles" | |
}, | |
{ | |
"artist": "Arcade Fire", | |
"album": "The suburbs" | |
}, | |
{ | |
"artist": "MGMT", | |
"album": "Congratulations" | |
}, | |
{ | |
"artist": "LCD Soundsystem", | |
"album": "This is happening" | |
} | |
], | |
"2011": [ | |
{ | |
"artist": "Radiohead", | |
"album": "The king of limbs" | |
}, | |
{ | |
"artist": "Arctic Monkeys", | |
"album": "Suck it and see" | |
}, | |
{ | |
"artist": "The Black Keys", | |
"album": "El camino" | |
}, | |
{ | |
"artist": "Wilco", | |
"album": "The Whole Love" | |
}, | |
{ | |
"artist": "The Flaming Lips", | |
"album": "24 hours song skull" | |
}, | |
{ | |
"artist": "PJ Harvey", | |
"album": "Let England Shake" | |
}, | |
{ | |
"artist": "TV on the Radio", | |
"album": "Nine types of light" | |
}, | |
{ | |
"artist": "My Morning Jacket", | |
"album": "Circuital" | |
} | |
], | |
"2012": [ | |
{ | |
"artist": "The Flaming Lips", | |
"album": "The Flaming Lips and heavy fewnds" | |
} | |
], | |
"2013": [ | |
{ | |
"artist": "The Strokes", | |
"album": "Comedown machine" | |
}, | |
{ | |
"artist": "Arctic Monkeys", | |
"album": "AM" | |
}, | |
{ | |
"artist": "Franz Ferdinand", | |
"album": "Right thoughts, right words, right actions" | |
}, | |
{ | |
"artist": "Phoenix", | |
"album": "Bankrupt!" | |
}, | |
{ | |
"artist": "Arcade Fire", | |
"album": "Reflektor" | |
}, | |
{ | |
"artist": "MGMT", | |
"album": "MGMT" | |
}, | |
{ | |
"artist": "The Flaming Lips", | |
"album": "The Time Has Come to Shoot You Down... What a Sound" | |
}, | |
{ | |
"artist": "Yeah Yeah Yeahs", | |
"album": "Mosquito" | |
} | |
], | |
"2014": [ | |
{ | |
"artist": "Interpol", | |
"album": "El pintor" | |
}, | |
{ | |
"artist": "The Black Keys", | |
"album": "Turn blue" | |
}, | |
{ | |
"artist": "Beck", | |
"album": "Morning Phase" | |
}, | |
{ | |
"artist": "The Flaming Lips", | |
"album": "With a Little Help from My Fwends" | |
}, | |
{ | |
"artist": "The Flaming Lips", | |
"album": "Atlas Eets Christmas" | |
}, | |
{ | |
"artist": "TV on the Radio", | |
"album": "Seeds" | |
} | |
], | |
"2015": [ | |
{ | |
"artist": "Wilco", | |
"album": "Star Wars" | |
}, | |
{ | |
"artist": "My Morning Jacket", | |
"album": "The waterfall" | |
} | |
], | |
"2016": [ | |
{ | |
"artist": "Radiohead", | |
"album": "A moon shaped pool" | |
}, | |
{ | |
"artist": "The Strokes", | |
"album": "Future Present Past" | |
}, | |
{ | |
"artist": "Wilco", | |
"album": "Schmilco" | |
}, | |
{ | |
"artist": "PJ Harvey", | |
"album": "The Hope Six Demolition Project" | |
} | |
], | |
"2017": [ | |
{ | |
"artist": "Phoenix", | |
"album": "Ti amo" | |
}, | |
{ | |
"artist": "Arcade Fire", | |
"album": "Everything Now" | |
}, | |
{ | |
"artist": "Beck", | |
"album": "Colors" | |
}, | |
{ | |
"artist": "LCD Soundsystem", | |
"album": "American Dream" | |
}, | |
{ | |
"artist": "The Flaming Lips", | |
"album": "Oczy Mlody" | |
} | |
], | |
"2018": [ | |
{ | |
"artist": "Interpol", | |
"album": "Marauder" | |
}, | |
{ | |
"artist": "Arctic Monkeys", | |
"album": "Tranquility base hotel & casino" | |
}, | |
{ | |
"artist": "Franz Ferdinand", | |
"album": "Always ascending" | |
}, | |
{ | |
"artist": "MGMT", | |
"album": "Little Dark Age" | |
} | |
], | |
"2019": [ | |
{ | |
"artist": "Interpol", | |
"album": "A fine mess" | |
}, | |
{ | |
"artist":"The Black Keys", | |
"album": "Let's rock" | |
}, | |
{ | |
"artist": "Beck", | |
"album": "Hyperspace" | |
}, | |
{ | |
"artist": "Wilco", | |
"album": "Ode to joy" | |
}, | |
{ | |
"artist": "The Flaming Lips", | |
"album": "King's mouth" | |
} | |
], | |
"2020": [ | |
{ | |
"artist": "The Strokes", | |
"album": "The new abnormal" | |
}, | |
{ | |
"artist": "The Flaming Lips", | |
"album": "Deap Lips" | |
} | |
] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment