Published
Edited
Dec 16, 2021
6 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
data = rocketLaunchesTable.map(d => {
return {
...d,
launchCountry: d.location.country
}
})
Insert cell
Insert cell
Insert cell
// cbrewer = chroma.scale(['#fafa6e','#2A4858'])
// .mode('lch').colors(9)
Insert cell
Insert cell
// We define a scale
color = d3.scaleOrdinal()
.domain(countries)
.range(cbrewer)
Insert cell
Insert cell
Insert cell
Insert cell
chart = {
const svg = d3.select(DOM.svg(width, height));
// Make a function that will rerun on each tick of the simulation
const ticked = () => {
const u = svg
.selectAll('circle')
.data(data, d => d.name)
u.enter()
.append('circle')
.attr('r', 5)
.merge(u)
.attr('cx', d => d.x)
.attr('cy', d => d.y)
u.exit()
.remove()
}
const simulation = d3.forceSimulation(data)
.force("charge", d3.forceManyBody() // this pushes points (+together,-apart)
.strength(10))
.force('collision', d3.forceCollide() // this e
.radius(5))
.force("center", d3.forceCenter(width / 2, height / 2))
.on('tick', ticked)

return svg.node()
}
Insert cell
Insert cell
Insert cell
Insert cell
chart_cluster = {
const svg = d3.select(DOM.svg(width, height));
// Make a function that will rerun on each tick of the simulation
const ticked = () => {
const u = svg
.selectAll('circle')
.data(data)
u.enter()
.append('circle')
.attr('r', 5)
.merge(u)
.attr('cx', d => d.x)
.attr('cy', d => d.y)
u.exit().remove()
}
const simulation = d3.forceSimulation(data)
.force("charge", d3.forceManyBody() // this pushes points (+together,-apart)
.strength(-5))
.force('collision', d3.forceCollide()
.radius(5))
.force("center", d3.forceCenter(width / 2, height / 2))
// align clump based on category
.force('x', d3.forceX().x(d=> xScale(d.launchCountry)))
// we can blind align the y axis to 0 so that things are single file
.force('y', d3.forceY().y(0))
.on('tick', ticked)

return svg.node()
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
chart_cluster_drag = {
const svg = d3.select(DOM.svg(width, height));
// Let's add some text attributes for each country
const labels = svg.selectAll('text')
.data(countries)
.enter()
.append('text')
.attr('x', d => xScale(d) + 10)
.attr('y', height/2 +40)
.attr('font-size', 14)
.text(d => d);
const nodes = svg
.selectAll('circle').data(data)
.enter()
.append('circle')
.attr('fill', d => color(d.launchCountry))
.attr('r', 5);
// Make a function that will rerun on each tick of the simulation
const ticked = () => {
nodes
.attr('cx', d => d.x)
.attr('cy', d => d.y)
}
// Then, we need some drag event handlers
const dragstarted = (d) => {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}

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

const dragended = (d) => {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
// Lastly, we attach them
nodes.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
const simulation = d3.forceSimulation(data)
.force("charge", d3.forceManyBody() // this pushes points (+together,-apart)
.strength(-5)
.distanceMax(100))
.force('collision', d3.forceCollide()
.radius(5))
.force("center", d3.forceCenter(width / 2, height / 2))
// align clump based on category
.force('x', d3.forceX().x(d=> xScale(d.launchCountry)))
// we can blind align the y axis to 0 so that things are single file
.force('y', d3.forceY().y(0))
.on('tick', ticked)

return svg.node()
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
filter = {
const svg = `<svg xmlns="http://www.w3.org/2000/svg">
<filter id="gooey">
<feGaussianBlur in="SourceGraphic" stdDeviation="10" color-interpolation-filters="sRGB" result="blur" />
<feColorMatrix class="blurValues" in="blur" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 18 -7" />
</filter>
</svg>`;
const blob = new Blob([svg], { type: 'image/svg+xml' });
const url = URL.createObjectURL(blob);

const filter = `url('${url}#gooey')`;
return filter;
}
Insert cell
chart_cluster_drag_gooey = {
const svg = d3.select(DOM.svg(width, height));
// add labels to each cluster!
const group = svg
.append("g")
// .attr("filter", filter) //Set the filter on the container... it's too large
const nodes = group
.selectAll('circle').data(data)
.enter()
.append('circle')
.attr('r', 5);
// Make a function that will rerun on each tick of the simulation
const ticked = () => {
nodes
.attr('cx', d => d.x)
.attr('cy', d => d.y)
}
// Then, we need some drag event handlers
const dragstarted = (d) => {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}

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

const dragended = (d) => {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
// Lastly, we attach the drag handlers
nodes.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
const simulation = d3.forceSimulation(data)
.force("charge", d3.forceManyBody() // this pushes points (+together,-apart)
.strength(-10)
.distanceMax(100))
.force('collision', d3.forceCollide()
.radius(5))
.force("center", d3.forceCenter(width / 2, height / 2))
.force('x', d3.forceX().x(d=> xScale(d.launchCountry))
// .strength(0.2)// keep between 0 and 1
)
.force('y', d3.forceY().y(0))
// .force('r', d3.forceRadial(width / 2, height / 2))
.on('tick', ticked)

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