Published
Edited
Aug 27, 2020
Importers
1 star
Insert cell
md`# Scatter plot`
Insert cell
getScatterPlot = function(data, metrics=[], {
colorScale="interpolatePuBu",
tooltipMetrics=[],
}={}) {
// parse data
const accessors = [
metrics[0] ? d => d[metrics[0]] : d => d,
metrics[1] ? d => d[metrics[1]] : d => d,
metrics[2] ? d => d[metrics[2]] : d => d,
]
// set up dimensions & chart elements
const dms = getDimensions({
width: width,
height: 500,
marginTop: 50,
marginBottom: 50,
marginLeft: 100,
})
const {wrapper, svg, bounds} = drawChart(dms)
const xScale = getScaleWithAxis(
"x", dms, data, accessors[0], bounds, metrics[0]
)
const x = d => xScale(accessors[0](d))
const yScale = getScaleWithAxis(
"y", dms, data, accessors[1], bounds, metrics[1]
)
const y = d => yScale(accessors[1](d))
const metric2Values = [...new Set(data.map(accessors[2]))]
const colorMetricType = getMetricType(metric2Values)
const colorScaleScale = getColorScaleWithLegend(
dms, data, accessors[2], bounds, colorScale, metrics[2]
)
const color = d => colorScaleScale(accessors[2](d))
// add tooltip
const tooltipWidth = 220
const tooltip = getTooltip(wrapper, tooltipWidth)
const sortedData = [...data].sort((a, b) => accessors[0](a) > accessors[0](b) ? -1 : 1)
// draw data
bounds.selectAll("circle")
.data(sortedData)
.join("circle")
.attr("cx", x)
.attr("cy", y)
.attr("r", 5)
.attr("fill", color)
// add interaction
const delaunay = d3.Delaunay.from(sortedData.map(d => ([
x(d),
y(d),
])))
bounds.append("rect")
.attr("width", dms.boundedWidth)
.attr("height", dms.boundedHeight)
.style("fill", "transparent")
.on("mousemove", function(e) {
const [mouseX, mouseY] = d3.mouse(this)
const index = delaunay.find(mouseX, mouseY)
const point = sortedData[index]
let parsedX = x(point) + dms.marginLeft
if (parsedX > dms.width - tooltipWidth - 10) parsedX -= tooltipWidth
let parsedY = y(point) + dms.marginTop
tooltip.style("opacity", 1)
tooltip.style("transform", `translate(${parsedX}px, calc(${parsedY > dms.height - 200 ? -100 : 0}% + ${parsedY}px))`)

tooltip.html([
`<div><strong>${metrics[0]} (x)</strong>: ${ accessors[0](point) }</div>`,
`<div><strong>${metrics[1]} (y)</strong>: ${ accessors[1](point) }</div>`,
`<div><strong>${metrics[2]} (color)</strong>: ${ accessors[2](point) }</div>`,
...tooltipMetrics.map(metric => (
`<div><strong>${ metric }</strong>: ${ point[metric] }</div>`
)),
].join(" "))
})
.on("mouseleave", metric => {
tooltip.style("opacity", 0)
})
return wrapper.node();
}
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more