<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-legend/2.24.0/d3-legend.min.js"></script>
<title>Basic Scatter Plot</title>
<style>
body {
position: fixed;
top: 0px;
bottom: 0px;
left: 0px;
right: 0px;
margin: 0px;
}
.domain {
display: none;
}
.tick line {
stroke: #C0C0BB;
}
.tick text, .legendCells text {
fill: #8E8883;
font-size: 28pt;
font-family: sans-serif;
}
.axis-label, .legend-label {
fill: #635F5D;
font-size: 50pt;
font-family: sans-serif;
}
</style>
</head>
<body>
<svg></svg>
<script>
const scatterPlot = (() => {
const xScale = d3.scaleLinear();
const yScale = d3.scaleLinear();
const colorScale = d3.scaleOrdinal();
const xAxis = d3.axisBottom().scale(xScale);
const yAxis = d3.axisLeft().scale(yScale);
const colorLegend = d3.legendColor()
.scale(colorScale)
.shape('circle');
return (svg, props) => {
const {
data,
width,
height,
margin,
xValue,
xLabel,
xLabelOffset,
xAxisTickPadding,
yValue,
yLabel,
yLabelOffset,
yAxisTicks,
yAxisTickPadding,
colorValue,
colorScheme,
colorLabel,
colorLegendX,
colorLegendY,
colorLegendLabelX,
colorLegendLabelY,
markFillOpacity,
markSize
} = props;
colorScale.range(colorScheme);
svg
.attr('width', width)
.attr('height', height);
let g = svg.selectAll('g').data([null]);
g = g.enter().append('g')
.merge(g)
.attr('transform', `translate(${margin.left},${margin.top})`);
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
xAxis
.tickPadding(xAxisTickPadding)
.tickSize(-innerHeight);
yAxis
.ticks(yAxisTicks)
.tickPadding(yAxisTickPadding)
.tickSize(-innerWidth);
let xAxisG = g.selectAll('.x-axis').data([null]);
xAxisG = xAxisG.enter().append('g').attr('class', 'x-axis')
.merge(xAxisG)
.attr('transform', `translate(0, ${innerHeight})`);
let yAxisG = g.selectAll('.y-axis').data([null]);
yAxisG = yAxisG.enter().append('g').attr('class', 'y-axis')
.merge(yAxisG);
let colorLegendG = g.selectAll('.color-legend').data([null]);
colorLegendG = colorLegendG.enter().append('g').attr('class', 'color-legend')
.merge(colorLegendG)
.attr('transform', `translate(${innerWidth + colorLegendX}, ${colorLegendY})`);
const xAxisLabel = xAxisG.selectAll('.axis-label').data([null]);
xAxisLabel
.enter().append('text')
.attr('class', 'axis-label')
.merge(xAxisLabel)
.attr('x', innerWidth / 2)
.attr('y', xLabelOffset)
.text(xLabel);
const yAxisLabel = yAxisG.selectAll('.axis-label').data([null]);
yAxisLabel
.enter().append('text')
.attr('class', 'axis-label')
.attr('y', -yLabelOffset)
.attr('transform', `rotate(-90)`)
.style('text-anchor', 'middle')
.merge(yAxisLabel)
.attr('x', -innerHeight / 2)
.text(yLabel);
const colorLegendLabel = colorLegendG.selectAll('.legend-label').data([null]);
colorLegendLabel
.enter().append('text')
.attr('class', 'legend-label')
.attr('x', colorLegendLabelX)
.attr('y', colorLegendLabelY)
.merge(colorLegendLabel)
.text(colorLabel);
xScale
.domain(d3.extent(data, xValue))
.range([0, innerWidth])
.nice();
yScale
.domain(d3.extent(data, yValue))
.range([innerHeight, 0])
.nice();
const marks = g.selectAll('.circle-mark').data(data);
marks.exit().remove();
marks
.enter().append('circle')
.attr('class', 'circle-mark')
.merge(marks)
.attr('fill-opacity', markFillOpacity)
.attr('r', markSize)
.attr('cx', d => xScale(xValue(d)))
.attr('cy', d => yScale(yValue(d)))
.attr('fill', d => colorScale(colorValue(d)));
xAxisG.call(xAxis);
yAxisG.call(yAxis);
colorLegendG.call(colorLegend)
.selectAll('.cell text')
.attr('dy', '0.1em');
};
})();
const row = d => {
d.petalLength = +d.petalLength;
d.petalWidth = +d.petalWidth;
d.sepalLength = +d.sepalLength;
d.sepalWidth = +d.sepalWidth;
return d;
};
d3.csv('iris.csv', row, data => {
const update = () => {
scatterPlot(d3.select('svg'), {
data,
width: document.body.clientWidth,
height: document.body.clientHeight,
margin: { left: 120, right: 300, top: 20, bottom: 120 },
xValue: d => d.sepalLength,
xLabel: 'Sepal Length',
xLabelOffset: 100,
xAxisTickPadding: 15,
yValue: d => d.petalLength,
yLabel: 'Petal Length',
yLabelOffset: 60,
yAxisTicks: 5,
yAxisTickPadding: 15,
colorValue: d => d.species,
colorLabel: 'Species',
colorScheme: d3.schemeCategory10,
colorLegendX: 60,
colorLegendY: 150,
colorLegendLabelX: -30,
colorLegendLabelY: -40,
markFillOpacity: 0.6,
markSize: 8
});
};
update();
window.addEventListener('resize', update);
});
</script>
</body>
</html>
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