Public
Edited
Oct 17, 2023
Insert cell
Insert cell
Insert cell
Insert cell
alphabet = [..."ABCDEFGHIJKLMNOPQRSTUVWXYZ"]
Insert cell
{
let data = d3.shuffle(alphabet.slice())
.slice(Math.floor(Math.random() * 10) + 5)
.sort(d3.ascending);
const width = 500;
const height = 50;
const margin = {top: 10, bottom: 10, left: 50, right: 10}
const svg = d3.create("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);

const g = svg.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`)

const yScale = d3.scalePoint()
.domain(['enter', 'update', 'exit'])
.range([0, height]);

const xScale = d3.scalePoint()
.domain(alphabet)
.range([10, width])

g.append("g")
.call(d3.axisLeft(yScale))

while (true) {

// yield svg.node()
yield data

// Selection
const textSelection = g.selectAll(".letter")
.data(data, d => d);

// Enter
textSelection.enter().append("text")
.attr("class", "letter")
.attr("y", yScale('enter') + 5)
.attr("x", d => xScale(d))
.style("font", "14px sans-serif")
.style("fill", "green")
.text(d => d);

// Update
textSelection
.transition()
.duration(1000)
.attr("y", yScale('update') + 5)
.style("fill", "#000");

// Exit
textSelection.exit()
.transition()
.duration(1000)
.style("fill", "red")
.attr("y", yScale('exit') + 5)
.transition()
.duration(1000)
.style("opacity", 0)
.remove();
await Promises.delay(3000);
data = d3.shuffle(alphabet.slice())
.slice(Math.floor(Math.random() * 10) + 5)
.sort(d3.ascending);

}
}
Insert cell
Insert cell
Insert cell
{
let data = d3.shuffle(alphabet.slice())
.slice(Math.floor(Math.random() * 10) + 5)
.sort(d3.ascending);
const width = 500;
const height = 50;
const margin = {top: 10, bottom: 10, left: 50, right: 10}
const svg = d3.create("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);

const g = svg.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`)

const yScale = d3.scalePoint()
.domain(['enter', 'update', 'exit'])
.range([0, height]);

const xScale = d3.scalePoint()
.domain(alphabet)
.range([10, width])

g.append("g")
.call(d3.axisLeft(yScale))

while (true) {

yield svg.node()
yield data
g.selectAll(".letter")
.data(data, d => d)
.join(
enter => enter.append("text")
.attr("fill", "green")
.attr("class", "letter")
.attr("x", d => xScale(d))
.attr("y", yScale('enter') + 5)
.style("font", "14px sans-serif")
.text(d => d),
update => update
.attr("fill", "black")
.call(update => update.transition()
.attr("y", yScale('update') + 5)),
exit => exit
.attr("fill", "red")
.call(exit => exit.transition()
.attr("y", yScale('exit') + 5)
.transition()
.remove())
); // Anything we add after our join will apply to the enter + update elements that remain

// If we don't care about handling enter + update differently, and we just want to remove our exited elements, You can do it all this way.
g.selectAll(".letter")
.data(data, d => d)
.join("text")
.attr("class", "letter")
.attr("y", yScale('enter') + 5)
.attr("x", d => xScale(d))
.style("font", "14px sans-serif")
.text(d => d)

await Promises.delay(3000);
data = d3.shuffle(alphabet.slice())
.slice(Math.floor(Math.random() * 10) + 5)
.sort(d3.ascending);

}
}
Insert cell
Insert cell
Insert cell
{
const width = window.innerWidth;
const height = 200;

const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)

const x = d3.scalePoint()
.domain([0, 1, 2, 3, 4])
.range([0, width])
.padding(.5)

svg.selectAll("circle")
.data(d3.range(5).map(Object))
.join("circle")
.attr("cx", (_, i) => x(i))
.attr("cy", height / 2)
.attr("r", 25)

return svg.node()
}
Insert cell
Insert cell
Insert cell
{
const width = 600;
const height = 400;
const margin = { top: 20, bottom: 20, left: 50, right: 50 };

const div = htl.html`<div></div>`;

const categories = d3.groups(iris, d => d.species)

const buttons = d3.select(div)
.selectAll("button")
.data(categories)
.join("button");

buttons.text(d => d[0])
const svg = d3.select(div)
.append("div")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);

const g = svg
.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`);

const x = d3
.scaleLinear()
.domain(d3.extent(iris, (d) => d["sepalLength"]))
.range([0, width]);

const y = d3
.scaleLinear()
.domain(d3.extent(iris, (d) => d["sepalWidth"]))
.range([height, 0]);

const color = d3.scaleOrdinal()
.domain(categories.map(d => d[0]))
.range(d3.schemeDark2)

g.append("g")
.call(d3.axisLeft(y));

g.append("g")
.attr("transform", `translate(0, ${height})`)
.call(d3.axisBottom(x))

const circles = g
.selectAll("circle")
.data(iris.filter(d => d.species == 'setosa'))
.join("circle")
.attr("r", 4)
.style("stroke", "#000")
.attr("cx", (d) => x(d.sepalLength))
.attr("cy", (d) => y(d.sepalWidth))
.style("fill", d => color(d.species));

buttons.on("click", (event, d) => {

})


return div
}
Insert cell
categories = d3.groups(iris, (d) => d.species)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
iris.csv
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
{
const width = 500;
const height = 200;
const r = 50;

const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)

const circle = svg.append("circle")
.attr("r", r)
.attr("cx", r)
.attr("cy", height / 2)
.transition().duration(2000)
.attr("cx", width - r)
.transition()
.attr("cx", r)

return svg.node()
}
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