An example of a stylized scatter plot with re-usable code organization using D3 v4.
Last active
August 3, 2017 13:44
-
-
Save curran/ffcf1dac1f301cf7ec7559fa729b647f to your computer and use it in GitHub Desktop.
Scatter Plot with Size Legend
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
license: mit | |
border: yes |
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> | |
<title>Solution</title> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<style> | |
body { | |
margin: 0px; | |
} | |
.axis .tick line { | |
stroke-width: 2px; | |
stroke: #dddddd; | |
} | |
.axis .tick text { | |
font-size: 30px; | |
fill: #8E8883; | |
} | |
.axis .domain { | |
display: none; | |
} | |
.axis__label { | |
text-anchor: middle; | |
font-size: 50px; | |
fill: #635F5D; | |
} | |
.legend .tick text { | |
font-size: 30px; | |
fill: #8E8883; | |
font-family: sans-serif; | |
alignment-baseline: middle; | |
} | |
.legend__label { | |
font-size: 45px; | |
fill: #635F5D; | |
font-family: sans-serif; | |
} | |
</style> | |
</head> | |
<body> | |
<svg width="960" height="500"></svg> | |
<script> | |
const xValue = d => d.sepalLength; | |
const yValue = d => d.petalLength; | |
const sizeValue = d => d.petalWidth; | |
const sizeMax = 10; | |
const xLabel = "Sepal Length"; | |
const yLabel = "Petal Length"; | |
const sizeLabel = "Petal Width"; | |
const margin = {top: 30, right: 300, bottom: 100, left: 100}; | |
const svg = d3.select("svg"); | |
const width = +svg.attr("width"); | |
const height = +svg.attr("height"); | |
const innerWidth = width - margin.left - margin.right; | |
const innerHeight = height - margin.top - margin.bottom; | |
const xScale = d3.scaleLinear().range([0, innerWidth]); | |
const yScale = d3.scaleLinear().range([innerHeight, 0]); | |
const sizeScale = d3.scaleSqrt() | |
.range([0, sizeMax]); | |
const xAxis = d3.axisBottom() | |
.scale(xScale) | |
.tickSizeInner(-innerHeight) | |
.tickPadding(15); | |
const yAxis = d3.axisLeft() | |
.scale(yScale) | |
.tickSizeInner(-innerWidth) | |
.ticks(5) | |
.tickPadding(10); | |
const g = svg.append("g") | |
.attr("transform", `translate(${margin.left}, ${margin.top})`); | |
const xAxisG = g.append("g") | |
.attr("class", "axis") | |
.attr("transform", `translate(0, ${innerHeight})`); | |
const yAxisG = g.append("g") | |
.attr("class", "axis"); | |
xAxisG | |
.append("text") | |
.attr("class", "axis__label") | |
.attr("x", innerWidth / 2) | |
.attr("y", 85) | |
.text(xLabel); | |
yAxisG | |
.append("text") | |
.attr("class", "axis__label") | |
.attr("transform", "rotate(-90)") | |
.attr("x", -innerHeight / 2) | |
.attr("y", -45) | |
.text(yLabel); | |
function sizeLegend(selection, props){ | |
const sizeScale = props.sizeScale; | |
const positionX = props.positionX; | |
const positionY = props.positionY; | |
const ticksCount = props.ticks; | |
const tickFill = props.tickFill; | |
const tickSpacing = props.tickSpacing; | |
const tickPadding = props.tickPadding; | |
const label = props.label; | |
const labelX = props.labelX; | |
const labelY = props.labelY; | |
let legendG = selection | |
.selectAll(".legend--size") | |
.data([null]); | |
legendG = legendG | |
.enter().append("g") | |
.attr("class", "legend legend--size") | |
.merge(legendG) | |
.attr("transform", `translate(${positionX}, ${positionY})`); | |
const legendLabel = legendG | |
.selectAll(".legend__label") | |
.data([null]); | |
legendLabel | |
.enter().append("text") | |
.attr("class", "legend__label") | |
.merge(legendLabel) | |
.attr("x", labelX) | |
.attr("y", labelY) | |
.text(label); | |
const ticks = legendG | |
.selectAll(".tick") | |
.data(sizeScale.ticks(ticksCount).filter(d => d)); | |
const ticksEnter = ticks | |
.enter().append("g") | |
.attr("class", "tick"); | |
ticksEnter | |
.merge(ticks) | |
.attr("transform", (d, i) => `translate(0, ${i * tickSpacing})`); | |
ticks.exit().remove(); | |
ticksEnter | |
.append("circle") | |
.merge(ticks.select("circle")) | |
.attr("r", sizeScale) | |
.attr("fill", tickFill); | |
ticksEnter | |
.append("text") | |
.merge(ticks.select("text")) | |
.attr("x", tickPadding) | |
.text(d => d); | |
} | |
function render(data){ | |
xScale | |
.domain(d3.extent(data, xValue)) | |
.nice(); | |
yScale | |
.domain(d3.extent(data, yValue)) | |
.nice(); | |
sizeScale | |
.domain([0, d3.max(data, sizeValue)]); | |
xAxisG.call(xAxis); | |
yAxisG.call(yAxis); | |
const circles = g.selectAll("circle").data(data); | |
circles.exit().remove(); | |
circles | |
.enter().append("circle") | |
.attr("r", 5) | |
.merge(circles) | |
.attr("cx", d => xScale(xValue(d))) | |
.attr("cy", d => yScale(yValue(d))) | |
.attr("r", d => sizeScale(sizeValue(d))); | |
sizeLegend(svg, { | |
sizeScale: sizeScale, | |
positionX: 722, | |
positionY: 200, | |
ticks: 5, | |
tickFill: "black", | |
tickSpacing: 35, | |
tickPadding: 16, | |
label: "Petal Width", | |
labelX: -20, | |
labelY: -30 | |
}); | |
} | |
function type(d){ | |
d.sepalLength = +d.sepalLength; | |
d.sepalWidth = +d.sepalWidth; | |
d.petalLength = +d.petalLength; | |
d.petalWidth = +d.petalWidth; | |
return d; | |
} | |
d3.csv("iris.csv", type, render); | |
</script> | |
</body> | |
</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
sepalLength | sepalWidth | petalLength | petalWidth | species | |
---|---|---|---|---|---|
5.1 | 3.5 | 1.4 | 0.2 | setosa | |
4.9 | 3.0 | 1.4 | 0.2 | setosa | |
4.7 | 3.2 | 1.3 | 0.2 | setosa | |
4.6 | 3.1 | 1.5 | 0.2 | setosa | |
5.0 | 3.6 | 1.4 | 0.2 | setosa | |
5.4 | 3.9 | 1.7 | 0.4 | setosa | |
4.6 | 3.4 | 1.4 | 0.3 | setosa | |
5.0 | 3.4 | 1.5 | 0.2 | setosa | |
4.4 | 2.9 | 1.4 | 0.2 | setosa | |
4.9 | 3.1 | 1.5 | 0.1 | setosa | |
5.4 | 3.7 | 1.5 | 0.2 | setosa | |
4.8 | 3.4 | 1.6 | 0.2 | setosa | |
4.8 | 3.0 | 1.4 | 0.1 | setosa | |
4.3 | 3.0 | 1.1 | 0.1 | setosa | |
5.8 | 4.0 | 1.2 | 0.2 | setosa | |
5.7 | 4.4 | 1.5 | 0.4 | setosa | |
5.4 | 3.9 | 1.3 | 0.4 | setosa | |
5.1 | 3.5 | 1.4 | 0.3 | setosa | |
5.7 | 3.8 | 1.7 | 0.3 | setosa | |
5.1 | 3.8 | 1.5 | 0.3 | setosa | |
5.4 | 3.4 | 1.7 | 0.2 | setosa | |
5.1 | 3.7 | 1.5 | 0.4 | setosa | |
4.6 | 3.6 | 1.0 | 0.2 | setosa | |
5.1 | 3.3 | 1.7 | 0.5 | setosa | |
4.8 | 3.4 | 1.9 | 0.2 | setosa | |
5.0 | 3.0 | 1.6 | 0.2 | setosa | |
5.0 | 3.4 | 1.6 | 0.4 | setosa | |
5.2 | 3.5 | 1.5 | 0.2 | setosa | |
5.2 | 3.4 | 1.4 | 0.2 | setosa | |
4.7 | 3.2 | 1.6 | 0.2 | setosa | |
4.8 | 3.1 | 1.6 | 0.2 | setosa | |
5.4 | 3.4 | 1.5 | 0.4 | setosa | |
5.2 | 4.1 | 1.5 | 0.1 | setosa | |
5.5 | 4.2 | 1.4 | 0.2 | setosa | |
4.9 | 3.1 | 1.5 | 0.1 | setosa | |
5.0 | 3.2 | 1.2 | 0.2 | setosa | |
5.5 | 3.5 | 1.3 | 0.2 | setosa | |
4.9 | 3.1 | 1.5 | 0.1 | setosa | |
4.4 | 3.0 | 1.3 | 0.2 | setosa | |
5.1 | 3.4 | 1.5 | 0.2 | setosa | |
5.0 | 3.5 | 1.3 | 0.3 | setosa | |
4.5 | 2.3 | 1.3 | 0.3 | setosa | |
4.4 | 3.2 | 1.3 | 0.2 | setosa | |
5.0 | 3.5 | 1.6 | 0.6 | setosa | |
5.1 | 3.8 | 1.9 | 0.4 | setosa | |
4.8 | 3.0 | 1.4 | 0.3 | setosa | |
5.1 | 3.8 | 1.6 | 0.2 | setosa | |
4.6 | 3.2 | 1.4 | 0.2 | setosa | |
5.3 | 3.7 | 1.5 | 0.2 | setosa | |
5.0 | 3.3 | 1.4 | 0.2 | setosa | |
7.0 | 3.2 | 4.7 | 1.4 | versicolor | |
6.4 | 3.2 | 4.5 | 1.5 | versicolor | |
6.9 | 3.1 | 4.9 | 1.5 | versicolor | |
5.5 | 2.3 | 4.0 | 1.3 | versicolor | |
6.5 | 2.8 | 4.6 | 1.5 | versicolor | |
5.7 | 2.8 | 4.5 | 1.3 | versicolor | |
6.3 | 3.3 | 4.7 | 1.6 | versicolor | |
4.9 | 2.4 | 3.3 | 1.0 | versicolor | |
6.6 | 2.9 | 4.6 | 1.3 | versicolor | |
5.2 | 2.7 | 3.9 | 1.4 | versicolor | |
5.0 | 2.0 | 3.5 | 1.0 | versicolor | |
5.9 | 3.0 | 4.2 | 1.5 | versicolor | |
6.0 | 2.2 | 4.0 | 1.0 | versicolor | |
6.1 | 2.9 | 4.7 | 1.4 | versicolor | |
5.6 | 2.9 | 3.6 | 1.3 | versicolor | |
6.7 | 3.1 | 4.4 | 1.4 | versicolor | |
5.6 | 3.0 | 4.5 | 1.5 | versicolor | |
5.8 | 2.7 | 4.1 | 1.0 | versicolor | |
6.2 | 2.2 | 4.5 | 1.5 | versicolor | |
5.6 | 2.5 | 3.9 | 1.1 | versicolor | |
5.9 | 3.2 | 4.8 | 1.8 | versicolor | |
6.1 | 2.8 | 4.0 | 1.3 | versicolor | |
6.3 | 2.5 | 4.9 | 1.5 | versicolor | |
6.1 | 2.8 | 4.7 | 1.2 | versicolor | |
6.4 | 2.9 | 4.3 | 1.3 | versicolor | |
6.6 | 3.0 | 4.4 | 1.4 | versicolor | |
6.8 | 2.8 | 4.8 | 1.4 | versicolor | |
6.7 | 3.0 | 5.0 | 1.7 | versicolor | |
6.0 | 2.9 | 4.5 | 1.5 | versicolor | |
5.7 | 2.6 | 3.5 | 1.0 | versicolor | |
5.5 | 2.4 | 3.8 | 1.1 | versicolor | |
5.5 | 2.4 | 3.7 | 1.0 | versicolor | |
5.8 | 2.7 | 3.9 | 1.2 | versicolor | |
6.0 | 2.7 | 5.1 | 1.6 | versicolor | |
5.4 | 3.0 | 4.5 | 1.5 | versicolor | |
6.0 | 3.4 | 4.5 | 1.6 | versicolor | |
6.7 | 3.1 | 4.7 | 1.5 | versicolor | |
6.3 | 2.3 | 4.4 | 1.3 | versicolor | |
5.6 | 3.0 | 4.1 | 1.3 | versicolor | |
5.5 | 2.5 | 4.0 | 1.3 | versicolor | |
5.5 | 2.6 | 4.4 | 1.2 | versicolor | |
6.1 | 3.0 | 4.6 | 1.4 | versicolor | |
5.8 | 2.6 | 4.0 | 1.2 | versicolor | |
5.0 | 2.3 | 3.3 | 1.0 | versicolor | |
5.6 | 2.7 | 4.2 | 1.3 | versicolor | |
5.7 | 3.0 | 4.2 | 1.2 | versicolor | |
5.7 | 2.9 | 4.2 | 1.3 | versicolor | |
6.2 | 2.9 | 4.3 | 1.3 | versicolor | |
5.1 | 2.5 | 3.0 | 1.1 | versicolor | |
5.7 | 2.8 | 4.1 | 1.3 | versicolor | |
6.3 | 3.3 | 6.0 | 2.5 | virginica | |
5.8 | 2.7 | 5.1 | 1.9 | virginica | |
7.1 | 3.0 | 5.9 | 2.1 | virginica | |
6.3 | 2.9 | 5.6 | 1.8 | virginica | |
6.5 | 3.0 | 5.8 | 2.2 | virginica | |
7.6 | 3.0 | 6.6 | 2.1 | virginica | |
4.9 | 2.5 | 4.5 | 1.7 | virginica | |
7.3 | 2.9 | 6.3 | 1.8 | virginica | |
6.7 | 2.5 | 5.8 | 1.8 | virginica | |
7.2 | 3.6 | 6.1 | 2.5 | virginica | |
6.5 | 3.2 | 5.1 | 2.0 | virginica | |
6.4 | 2.7 | 5.3 | 1.9 | virginica | |
6.8 | 3.0 | 5.5 | 2.1 | virginica | |
5.7 | 2.5 | 5.0 | 2.0 | virginica | |
5.8 | 2.8 | 5.1 | 2.4 | virginica | |
6.4 | 3.2 | 5.3 | 2.3 | virginica | |
6.5 | 3.0 | 5.5 | 1.8 | virginica | |
7.7 | 3.8 | 6.7 | 2.2 | virginica | |
7.7 | 2.6 | 6.9 | 2.3 | virginica | |
6.0 | 2.2 | 5.0 | 1.5 | virginica | |
6.9 | 3.2 | 5.7 | 2.3 | virginica | |
5.6 | 2.8 | 4.9 | 2.0 | virginica | |
7.7 | 2.8 | 6.7 | 2.0 | virginica | |
6.3 | 2.7 | 4.9 | 1.8 | virginica | |
6.7 | 3.3 | 5.7 | 2.1 | virginica | |
7.2 | 3.2 | 6.0 | 1.8 | virginica | |
6.2 | 2.8 | 4.8 | 1.8 | virginica | |
6.1 | 3.0 | 4.9 | 1.8 | virginica | |
6.4 | 2.8 | 5.6 | 2.1 | virginica | |
7.2 | 3.0 | 5.8 | 1.6 | virginica | |
7.4 | 2.8 | 6.1 | 1.9 | virginica | |
7.9 | 3.8 | 6.4 | 2.0 | virginica | |
6.4 | 2.8 | 5.6 | 2.2 | virginica | |
6.3 | 2.8 | 5.1 | 1.5 | virginica | |
6.1 | 2.6 | 5.6 | 1.4 | virginica | |
7.7 | 3.0 | 6.1 | 2.3 | virginica | |
6.3 | 3.4 | 5.6 | 2.4 | virginica | |
6.4 | 3.1 | 5.5 | 1.8 | virginica | |
6.0 | 3.0 | 4.8 | 1.8 | virginica | |
6.9 | 3.1 | 5.4 | 2.1 | virginica | |
6.7 | 3.1 | 5.6 | 2.4 | virginica | |
6.9 | 3.1 | 5.1 | 2.3 | virginica | |
5.8 | 2.7 | 5.1 | 1.9 | virginica | |
6.8 | 3.2 | 5.9 | 2.3 | virginica | |
6.7 | 3.3 | 5.7 | 2.5 | virginica | |
6.7 | 3.0 | 5.2 | 2.3 | virginica | |
6.3 | 2.5 | 5.0 | 1.9 | virginica | |
6.5 | 3.0 | 5.2 | 2.0 | virginica | |
6.2 | 3.4 | 5.4 | 2.3 | virginica | |
5.9 | 3.0 | 5.1 | 1.8 | virginica |
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
�PNG | |