Published
Edited
Jan 15, 2022
Insert cell
Insert cell
Insert cell
{
const svg = d3.create("svg")
.attr("width", dimensions.width)
.attr("height", dimensions.height)
.attr("viewBox", [0, 0, dimensions.width, dimensions.height])
.style("max-width", "100%")
.style("height", "auto")

const bounds = svg.append("g")
.style("transform", `translate(${dimensions.margin.left}px, ${dimensions.margin.top}px)`)

bounds.selectAll("circle")
.data(plotData)
.join("circle")
.attr("cx", d => xScale(xAccessor(d)))
.attr("cy", d => yScale(yAccessor(d)))
.attr("fill", d => colorScale(colorAccessor(d)))
.attr("r", radius)

bounds.append("g")
.call(xAxis)
.style("transform", `translateY(${boundedHeight}px)`)
.call(g => g.select(".domain").remove())
.call(g => g.selectAll(".tick line").clone()
.attr("y2", -(boundedHeight + dimensions.margin.top * 0.5))
.style("opacity", 0.1))
bounds.append("g")
.call(yAxis)
.call(g => g.select(".domain").remove())
.call(g => g.selectAll(".tick line").clone()
.attr("x2", boundedWidth + dimensions.margin.left * 0.5)
.style("opacity", 0.1))

const axisLabels = [
{x: 366, y: 435, text: "Bill length (in mm)"},
{x: 5, y: -4, text: "Bill depth (in mm)"}
]

bounds.selectAll("rect")
.data(labels)
.join("rect")
.attr("x", d => d.x)
.attr("y", d => d.y)
.attr("width", d => d.bbox.width + 2 * 4)
.attr("height", d => d.bbox.height + 2 * 2)
.attr("fill", "white")
.attr('transform', function(d) {
return `translate(-4, -${d.bbox.height * 0.8 + 2})`
})
bounds.selectAll("labels")
.data(labels)
.join("text")
.attr("class", "labels")
.attr("x", d => d.x)
.attr("y", d => d.y)
.attr("fill", d => colorScale(d.text))
.text(d => d.text)

bounds.selectAll("axis-labels")
.data(axisLabels)
.join("text")
.attr("class", "axis-labels")
.attr("x", d => d.x)
.attr("y", d => d.y)
.text(d => d.text)
.call(d3.drag().on("drag", positionLabel))

function positionLabel(e, d) {
d3.select(this)
.attr("x", d.x = e.x)
.attr("y", d.y = e.y)
}

return svg.node()
}
Insert cell
labels = [
{x: 72, y: 28, text: "Adelie"},
{x: 332, y: 138, text: "Chinstrap"},
{x: 298, y: 364, text: "Gentoo"},
]
Insert cell
svgLabels = d3.create("svg").attr("viewBox", [0, 0, 0, 0])
Insert cell
measure = {
svgLabels.selectAll("text")
.data(labels)
.join("text")
.attr("class", "labels")
.attr("x", d => d.x)
.attr("y", d => d.y)
.text(d => d.text)
return svgLabels.node()
}
Insert cell
update = (data) =>
svgLabels.selectAll("text")
.data(data)
.each(function(d) {d.bbox = this.getBBox()})
Insert cell
update(labels)
Insert cell
labels.map(d => d.bbox.width)
Insert cell
data = await d3.csv("https://raw.githubusercontent.com/mwaskom/seaborn-data/master/penguins.csv")
Insert cell
plotData = data.filter(d => d.bill_length_mm !== "")
Insert cell
xAxis = d3.axisBottom()
.scale(xScale)
.ticks(5)
Insert cell
yAxis = d3.axisLeft()
.scale(yScale)
.ticks(8)
Insert cell
xAccessor = d => d.bill_length_mm
Insert cell
yAccessor = d => d.bill_depth_mm
Insert cell
colorAccessor = d => d.species
Insert cell
radius = 4
Insert cell
xScale = d3.scaleLinear()
.domain(d3.extent(plotData, xAccessor))
.range([0, boundedWidth])
.nice()
Insert cell
yScale = d3.scaleLinear()
.domain(d3.extent(plotData, yAccessor))
.range([boundedHeight, 0])
.nice()
Insert cell
colorScale = d3.scaleOrdinal()
.domain(species)
.range(d3.schemeSet2.slice(0, 3))
Insert cell
species = [...new Set(plotData.map(d => d.species))]
Insert cell
dimensions = ({
width: 500,
height: 500,
margin: {
top: 20,
right: 20,
bottom: 40,
left: 40
}
})
Insert cell
boundedWidth = dimensions.width
- dimensions.margin.left
- dimensions.margin.right
Insert cell
boundedHeight = dimensions.height
- dimensions.margin.top
- dimensions.margin.bottom
Insert cell
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&family=JetBrains+Mono:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800&display=swap');
h2 {
font-family: Inter;
font-weight: 800;
letter-spacing: 1px;
font-size: 20px;
color: #7570b3;
}
text {
font-family: "JetBrains Mono"
}
.labels {
font-family: Inter;
font-weight: 600;
font-size: 15px;
}
.axis-labels {
cursor: pointer;
font-family: Inter;
font-weight: 300;
font-size: 11px;
}
</style>
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