Skip to content

Instantly share code, notes, and snippets.

@joshuajnoble
Created January 14, 2021 20:11
Show Gist options
  • Save joshuajnoble/68cb70a7997309cd58ac6d7d69920486 to your computer and use it in GitHub Desktop.
Save joshuajnoble/68cb70a7997309cd58ac6d7d69920486 to your computer and use it in GitHub Desktop.
A basic scatterplot in d3
function scatterPlot({
chart, /* this needs to be an SVG element */
width,
height,
data,
xfield,
yfield,
xdomain, /* min/max x values */
ydomain, /* min/max y values */
xpadding,
ypadding,
size, /* size of the dot */
title,
xlabel,
ylabel,
xgrid, /* show a grid true/false */
ygrid /* show a grid true/false */
}) {
let xAxisHeight = 30;
let yAxisHeight = 20;
let xAxisWidth = 20;
let yAxisWidth = 20;
let titleHeight = 30;
let textHeight = 10;
let figPadding = 40;
let topPadding = titleHeight + figPadding;
let leftPadding = figPadding + yAxisWidth;
let bottomPadding = figPadding + xAxisHeight;
let svg = chart.node();
let w = width - leftPadding - 30;
let h = height - topPadding - bottomPadding;
let xscale = d3
.scaleLinear()
.domain(xdomain)
.range([0, w]);
let yscale = d3
.scaleLinear()
.domain(ydomain)
.range([h, 0]);
let xvalue_scale = d3
.scaleLinear()
.domain(xdomain)
.range([0, w]);
let yvalue_scale = d3
.scaleLinear()
.domain(ydomain)
.range([h, 0]);
// Add x axis
let xAxis = d3
.axisBottom(xscale)
.tickPadding(4)
.tickSizeOuter(0);
chart
.append("g")
.attr("class", "x axis")
.attr(
"transform",
"translate(" + leftPadding + "," + (h + topPadding) + ")"
)
.call(xAxis);
// Add x axis label
chart
.append("text")
.attr(
"transform",
"translate(" +
(leftPadding + w / 2) +
" ," +
(height - figPadding + 10) +
")"
)
.style("text-anchor", "middle")
.text(xlabel);
// x axis
// Ref: https://bl.ocks.org/d3noob/c506ac45617cf9ed39337f99f8511218
if (xgrid) {
chart
.append("g")
.attr("class", "x grid")
.attr("transform", "translate(" + leftPadding + "," + topPadding + ")")
.call(
xAxis
.tickSize(h)
.tickFormat("")
.ticks(5)
);
}
// Add y axis
let yAxis = d3
.axisLeft(yscale)
.tickSizeOuter(0)
.ticks(4);
chart
.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + leftPadding + "," + topPadding + ")")
.call(yAxis);
// Add y axis label
chart
.append("text")
.attr(
"transform",
"rotate(-90)," +
"translate(" +
(0 - topPadding - h / 2 - 10) +
" ," +
(figPadding + textHeight / 2 - 15) +
")"
)
.style("text-anchor", "middle")
.text(ylabel);
// y grid
if (ygrid) {
chart
.append("g")
.attr("class", "y grid")
.attr("transform", "translate(" + leftPadding + "," + topPadding + ")")
.call(yAxis.tickSize(-w).tickFormat(""));
}
// create a new group, use `selectAll` to build an empty
// list context
let dots = chart
.append("g")
.attr("class", "dots")
.selectAll()
.data(data)
.enter()
.append("circle")
.attr("cx", d => leftPadding + xvalue_scale(d[xfield]))
.attr("cy", d => topPadding + yvalue_scale(d[yfield]))
.attr("r", size);
// Add title
chart
.append("text")
.attr("class", "title")
.attr("text-anchor", "middle")
.attr("x", w / 2 + leftPadding)
.attr("y", figPadding + titleHeight / 2)
.text(title);
return chart;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment