This viz allows you to button between each of the four datasets in Anscombe's quartet. Includes enlarged circles upon hover, a rainbow color scale for the circles, and delayed transitions between datasets.
xxxxxxxxxx
<html>
<body>
<div class="buttons"></div>
<br />
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
.circleGroups text {
font: 10px sans-serif;
}
.title {
font: 20px sans-serif;
}
.axis .tick {
stroke-width:1px;
stroke-dasharray: 2px 2px;
stroke-opacity: .5;
}
</style>
<script>
var margin = {top: 20, right: 10, bottom: 40, left: 40};
var width = 600 - margin.left - margin.right,
height = 600 - margin.top - margin.bottom;
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("class", "innerG")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var xScale = d3.scaleLinear()
.domain([0,20])
.range([0, width]);
var yScale = d3.scaleLinear()
.domain([0,20])
.range([height, 0]);
var xAxis = d3.axisBottom(xScale)
.tickSize(-height);
var yAxis = d3.axisLeft(yScale)
.tickSize(-width);
svg.append('g')
.attr('class', 'y axis')
.call(yAxis)
svg.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + height + ')')
.call(xAxis)
function dataSwap(datasetGroup) {
thisDataGroup = data.filter(function(d) { return d.group == datasetGroup})
thisDataGroup.sort(function(a, b) { return a.x - b.x });
console.log(datasetGroup)
svg.selectAll('.circleGroups')
.data(thisDataGroup)
.transition()
.delay(function(d, i) {return i*40;})
.attr('transform', function(d) {return 'translate(' + xScale(d.x) + ',' + yScale(d.y) + ')'})
d3.select('.title')
.text('Group ' + datasetGroup);
}
d3.tsv('quartet.tsv', function(error, data) {
if (error) return console.warn(error);
var groups = d3.set(data.map(function(d) { return d.group })).values();
window.data = data;
d3.select('.buttons')
.selectAll('button')
.data(groups)
.enter().append('button')
.text(function(d) { return 'Group' + d; })
.on('click', function(d) {
console.log(d)
dataSwap(d)
})
groupOneData = data.filter(function(d) { return d.group == "I" })
groupOneData.sort(function(a, b) { return a.x - b.x });
var colorScale = d3.scaleSequential(d3.interpolateRainbow)
.domain([0, groupOneData.length - 1])
groupOneData.filter(function(d) {return d.group})
svg.append('text')
.attr("class", 'title')
.text('Group ' + groupOneData[0].group)
var radiusSize = 10
var circleGroups = svg.selectAll(".circleGroups")
.data(groupOneData)
.enter().append('g')
.attr('class', 'circleGroups')
.attr('transform', function(d) {return 'translate(' + xScale(d.x) + ',' + yScale(d.y) + ')'})
.on('mouseenter', function(d) {
d3.select(this)
.append('text')
.attr('dx', 5)
.attr('dy', 10)
.text('(' + d.x + ',' + d.y + ')')
d3.selectAll('circle')
.style('opacity', 0.5)
d3.select(this)
.select('circle')
.transition()
.ease(d3.easeElastic)
.attr('r', 20)
.style('opacity', 1)
})
.on('mouseleave', function(d) {
d3.select(this)
.select('text')
.transition()
.style('opacity', 0)
.remove()
d3.select(this)
.select('circle')
.transition()
.ease(d3.easeElastic)
//
.attr('r', radiusSize)
d3.selectAll('circle')
.style('opacity', 1)
})
circleGroups.append('circle')
.attr('r', radiusSize)
.style('fill', function(d, i) { return colorScale(i); })
})
</script>
https://d3js.org/d3.v4.min.js