Public
Edited
Jul 14, 2023
Insert cell
Insert cell
Insert cell
chart = {
const svg = d3.select(DOM.svg(width, height));
svg.append('circle')
.attr('id', 'category_1')
.attr('r', height / 3)
.attr('cx', width / 2.8)
.attr('cy', height / 2)
.attr('fill', '#3bbc9b')
.attr('fill-opacity', 0.1)
.attr('stroke', '#3bbc9b')
.attr('stroke-opacity', 0.5)
.attr('opacity', 0)
svg.append('circle')
.attr('id', 'category_2')
.attr('r', height / 3)
.attr('cx', width / 1.8)
.attr('cy', height / 2)
.attr('fill', '#b97ebb')
.attr('fill-opacity', 0.1)
.attr('stroke', '#b97ebb')
.attr('stroke-opacity', 0.5)
.attr('opacity', 0);
const nodeGroup = svg.append("g").attr('id', 'nodes');
let simulation = d3.forceSimulation();
simulation = simulation
.force("collide", d3.forceCollide(d => d.radius + 3).iterations(12))
.force("charge", d3.forceManyBody())
.velocityDecay(0.75)
.alphaDecay(0.006)
.force("center", d3.forceCenter(width / 2, height / 2))
.force("y", d3.forceY(0))
.force("x", d3.forceX(0))
const ticked = () => {
nodeGroup.selectAll("circle")
.attr("cx", d => d.x)
.attr("cy", d => d.y);
}

simulation
.nodes(data)
.on("tick", ticked);
function draw() {
const node = nodeGroup.selectAll("circle")
.data(simulation.nodes(), d => d.id)
.enter().append("circle")
.attr("r", d => d.radius)
.attr('fill', d => d.type.color)
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
// node.attr("r", d => d.radius)
// .attr('fill', d => d.type.color)
// .call(d3.drag()
// .on("start", dragstarted)
// .on("drag", dragged)
// .on("end", dragended));
}
draw();
function split() {
simulation
.force("left", isolate(d3.forceX(width / 3).strength(0.3), d => d.type.value === 'Pizza lovers'))
.force("center", isolate(d3.forceX(width / 2.2).strength(0.3), d => d.type.value === 'Food lovers'))
.force("right", isolate(d3.forceX(width / 1.7).strength(0.3), d => d.type.value === 'Pasta lovers'))
.force("x", null)
.force("y", d3.forceY(height / 2).strength(0.3))
svg.select('#category_1')
.transition()
.delay(1000)
.duration(1000)
.attr('opacity', 1);
svg.select('#category_2')
.transition()
.delay(1000)
.duration(1000)
.attr('opacity', 1);
}
function isolate(force, filter) {
let initialize = force.initialize;
force.initialize = function() { initialize.call(force, data.filter(filter)); };
return force;
}
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(1).restart();
d.fx = d.x;
d.fy = d.y;
}

function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}

function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}

return Object.assign(svg.node(), { split });
}
Insert cell
Insert cell
Insert cell
Insert cell
data = d3.range(80).map((d, idx) => ({
id: idx,
type: people[~~d3.randomUniform(3)()],
radius: ~~d3.randomUniform(5, 15)(),
}))
Insert cell
d3 = require("d3@5")
Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

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