Part of the video course: D3.js in Motion.
An example scatter plot with color legend using D3 and d3-legend.
This data is from Pokemon, Pokemondb, and Bulbapedia. The dataset is about 1062 Pokemon, including their id, ndex, species, forme, first and second type, first ability and second ability, and etc.
forked from curran's block: Stylized Scatter Plot with Color Legend
xxxxxxxxxx
<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 {
margin: -3px;
}
.domain {
display: none;
}
.tick line {
stroke: #C0C0BB;
}
.tick text, .legendCells text {
fill: #8E8883;
font-size: 10pt;
font-family: sans-serif;
}
.axis-label, .legend-label {
fill: #635F5D;
font-size: 20.1088pt;
font-family: sans-serif;
}
</style>
</head>
<body>
<svg width="960" height="550"></svg>
<script>
const xValue = d => d.attack;
const xLabel = 'Attack';
const yValue = d => d.defense;
const yLabel = 'Defnse';
const colorValue = d => d.type1;
const colorLabel = 'Type1';
const margin = { left: 107, right: 177, top: 18, bottom: 128 };
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 g = svg.append('g')
.attr('transform', `translate(${margin.left},${margin.top})`);
const xAxisG = g.append('g')
.attr('transform', `translate(0, ${innerHeight})`);
const yAxisG = g.append('g');
const colorLegendG = g.append('g')
.attr('transform', `translate(${innerWidth + 60}, 150)`);
xAxisG.append('text')
.attr('class', 'axis-label')
.attr('x', innerWidth / 2)
.attr('y', 57)
.text(xLabel);
yAxisG.append('text')
.attr('class', 'axis-label')
.attr('x', -innerHeight / 2)
.attr('y', -48)
.attr('transform', `rotate(-90)`)
.style('text-anchor', 'middle')
.text(yLabel);
colorLegendG.append('text')
.attr('class', 'legend-label')
.attr('x', -5)
.attr('y', -32)
.text(colorLabel);
const xScale = d3.scaleLinear();
const yScale = d3.scaleLinear();
const colorScale = d3.scaleOrdinal()
.range(d3.schemeCategory10);
const xAxis = d3.axisBottom()
.scale(xScale)
.tickPadding(16)
.tickSize(-innerHeight);
const yAxis = d3.axisLeft()
.scale(yScale)
.ticks(8)
.tickPadding(9)
.tickSize(-innerWidth);
const colorLegend = d3.legendColor()
.scale(colorScale)
.shape('circle')
.shapeRadius(4);
const row = d => {
d.attack = +d.attack;
d.defense = +d.defense;
return d;
};
d3.csv('pokemon.csv', row, data => {
xScale
.domain(d3.extent(data, xValue))
.range([10, innerWidth])
.nice();
yScale
.domain(d3.extent(data, yValue))
.range([innerHeight, 0])
.nice();
g.selectAll('circle').data(data)
.enter().append('circle')
.attr('cx', d => xScale(xValue(d)))
.attr('cy', d => yScale(yValue(d)))
.attr('fill', d => colorScale(colorValue(d)))
.attr('fill-opacity', 0.50688)
.attr('r', 5);
xAxisG.call(xAxis);
yAxisG.call(yAxis);
colorLegendG.call(colorLegend)
.selectAll('.cell text')
.attr('dy', '0.05em');
});
</script>
</body>
</html>
https://d3js.org/d3.v4.min.js
https://cdnjs.cloudflare.com/ajax/libs/d3-legend/2.24.0/d3-legend.min.js