This scatterplot is constructed from a CSV file storing demographics in Midwestern state counties. The chart employs conventional margins and below listed D3 features:
View the gist on github Scatter-plot
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<!-- using the d3-tip library for tooltip -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.7.1/d3-tip.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
</style>
</head>
<body>
<div id="root" class="container"></div>
<script>
// A simple d3 scatter plot
"use strict";
/* ************************************* Set up: set global variables ******************************** */
const width = 500;
const height = 500;
const margin = {
top: 20,
right: 10,
bottom: 50,
left: 60
};
const radius = 2;
const color = "red";
// Chart width and height - accounting for margins
let drawWidth = width - margin.left - margin.right;
let drawHeight = height - margin.top - margin.bottom;
// Variables to display (i.e., which columns to select in the dataset)
const xVar = "percbelowpoverty";
const yVar = "percollege";
/* ****************** Create chart wrappers *************************** */
// Create an `svg` element to hold the chart (including axes and labels)
let svg = d3.select('#root')
.append('svg')
.attr('width', width)
.attr('height', height);
// Create a `g` element in which to render points
let chartG = svg.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
.attr('height', drawHeight)
.attr('width', drawWidth);
/* ******************* Load + prepare data ********************* */
d3.csv("midwest.csv", (err, rawData) => {
// Store data in a more generalized format for reusability
let data = rawData.map((d) => {
return {
x: +d[xVar],
y: +d[yVar],
label: d.county + ',' + d.state
};
});
/* ************************* Defining scales ********************** */
// Find the maximum x value for the x Scale, and multiply it by 1.05 (to add space)
let xMax = d3.max(data, (d) => +d.x) * 1.05;
// Find the minimum x value for the x Scale, and multiply it by .9 (to add space)
let xMin = d3.min(data, (d) => +d.x) * 0.9;
// Use `d3.scaleLinear` to define an `xScale` with the appropriate domain and range
let xScale = d3.scaleLinear()
.range([0, drawWidth])
.domain([xMin, xMax]);
// Find the maximum y value for the x Scale, and multiply it by 1.05 (to add space)
let yMax = d3.max(data, (d) => +d.y) * 1.05;
// Find the minimum y value for the x Scale, and multiply it by .9 (to add space)
let yMin = d3.min(data, (d) => +d.y) * 0.9;
// Use `d3.scaleLinear` to define a `yScale` with the appropriate domain and range
let yScale = d3.scaleLinear()
.range([0, drawHeight])
.domain([yMax, yMin]);
/* ************************** Defining axes ************************** */
// Define xAxis using d3.axisBottom, assigning the scale as `xScale`
let xAxis = d3.axisBottom(xScale);
// Define yAxis using d3.axisLeft(), assigning the scale as `yScale`
let yAxis = d3.axisLeft(yScale);
/* ********************* Rendering axes and labels ******************* */
// Append a `g` to the `svg` as an x axis label, specifying the 'transform' attribute to position it
// Use the `.call` method to render the axis in the `g`
let xAxisLabel = svg.append('g')
.attr('transform', 'translate(' + margin.left + ',' + (drawHeight + margin.top) + ')')
.attr('class', 'axis')
.call(xAxis);
// Append a `g` to the `svg` as a y axis label, specifying the 'transform' attribute to position it
// Use the `.call` method to render the axis in the `g`
let yAxisLabel = svg.append('g')
.attr('transform', 'translate(' + margin.left + ',' + (margin.top) + ')')
.attr('class', 'axis')
.call(yAxis);
// Add a title to the chart
let title = svg.append('text')
.attr('transform', `translate(${margin.left},15)`)
.text("Midwest Counties");
// Append a text element to the svg to label the x axis
let xAxisText = svg.append('text')
.attr('transform', `translate(${(margin.left + drawWidth / 2)}, ${(height - margin.bottom + 30)})`)
.attr('class', 'axis-label')
.text(xVar);
// Append a text element to the svg to label the y axis
svg.append('text')
.attr('transform', `translate( ${(margin.left - 30)},${(margin.top + drawHeight / 2)}) rotate(-90)`)
.attr('class', 'axis-label')
.text(yVar);
/* ******************************* Define Tooltip ************************************** */
let tip = d3.tip().attr('class', 'd3-tip').html(function (d) {
return d.label;
});
/* ************************************* Data Join ************************************** */
// Select all circles and bind data to the selection
let circles = chartG.selectAll('circle').data(data);
// Use the `.enter()` method to identify the entering elements, and assign their positions
// Then, merge on any updating circles and set all the properties
circles.enter().append('circle')
.on('mouseover', tip.show)
.on('mouseout', tip.hide)
.attr('r', (d) => radius)
.attr('fill', (d) => color)
.attr('label', (d) => d.label)
.style('fill-opacity', 0.3)
.merge(circles)
.transition().duration(500)
.attr('cx', (d) => xScale(d.x))
.attr('cy', (d) => yScale(d.y));
// Use the .exit() and .remove() methods to remove elements that are no longer in the data
circles.exit().remove();
// Add hovers using the d3-tip library
chartG.call(tip);
});
</script>
</body>
https://d3js.org/d3.v4.min.js
https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.7.1/d3-tip.js