Published
Edited
Jun 28, 2020
1 fork
3 stars
Insert cell
Insert cell
Insert cell
data = {
const text = await FileAttachment("data.csv").text();
return d3.csvParse(text, (d) => ({
r: radius,
x: width/2,
y: height/2,
ID: d.ID,
Location: d.Location,
Group: d.Group,
Class: d.Class,
Type: d.Type
}));
}
Insert cell
color = d3.scaleOrdinal(d3.schemeTableau10);
Insert cell
centerScale = d3.scalePoint().padding(1).range([0, width]);
Insert cell
forceStrength = 0.05;
Insert cell
simulation = d3.forceSimulation()
.force("collide",d3.forceCollide( function(d){
return d.r + 8 }).iterations(16)
)
.force("charge", d3.forceManyBody())
.force("y", d3.forceY().y(height / 2))
.force("x", d3.forceX().x(width / 2))
Insert cell
Insert cell
Insert cell
chart = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);
var circles = svg.selectAll("circle")
.data(data, function(d){ return d.ID ;});
const circlesEnter = circles.enter().append("circle")
.attr("r", function(d, i){ return d.r; })
.attr("cx", function(d, i){ return 175 + 25 * i + 2 * i ** 2; })
.attr("cy", function(d, i){ return 250; })
.style("fill", function(d, i){ return color(d.ID); })
.style("stroke", function(d, i){ return color(d.ID); })
.style("stroke-width", 10)
.style("pointer-events", "all")
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
circles = circles.merge(circlesEnter)
function ticked() {
circles
.attr("cx", function(d){ return d.x; })
.attr("cy", function(d){ return d.y; });
}

simulation
.nodes(data)
.on("tick", ticked);
function dragstarted(d,i) {
//console.log("dragstarted " + i)
if (!d3.event.active) simulation.alpha(1).restart();
d.fx = d.x;
d.fy = d.y;
}

function dragged(d,i) {
//console.log("dragged " + i)
d.fx = d3.event.x;
d.fy = d3.event.y;
}

function dragended(d,i) {
//console.log("dragended " + i)
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
var me = d3.select(this)
console.log(me.classed("selected"))
me.classed("selected", !me.classed("selected"))
d3.selectAll("circle")
.style("fill", function(d, i){ return color(d.ID); })
d3.selectAll("circle.selected")
.style("fill", "none")
}
function groupBubbles() {
hideTitles();

// @v4 Reset the 'x' force to draw the bubbles to the center.
simulation.force('x', d3.forceX().strength(forceStrength).x(width/ 2));

// @v4 We can reset the alpha value and restart the simulation
simulation.alpha(1).restart();
}
function splitBubbles(byVar) {
centerScale.domain(data.map(function(d){ return d[byVar]; }));
if(byVar == "all"){
hideTitles()
} else {
showTitles(byVar, centerScale);
}
// @v4 Reset the 'x' force to draw the bubbles to their year centers
simulation.force('x', d3.forceX().strength(forceStrength).x(function(d){
return centerScale(d[byVar]);
}));

// @v4 We can reset the alpha value and restart the simulation
simulation.alpha(2).restart();
}
function hideTitles() {
svg.selectAll('.title').remove();
}

function showTitles(byVar, scale) {
// Another way to do this would be to create
// the year texts once and then just hide them.
var titles = svg.selectAll('.title')
.data(scale.domain());
titles.enter().append('text')
.attr('class', 'title')
.merge(titles)
.attr('x', function (d) { return scale(d); })
.attr('y', 40)
.attr('text-anchor', 'middle')
.text(function (d) { return byVar + ' ' + d; });
titles.exit().remove()
}
console.log(sort)
splitBubbles(sort);
return svg.node();
}
Insert cell
Insert cell
mydata = {
const text = await FileAttachment("univ_agg_with_continent.csv").text();
return d3.csvParse(text, (d) => ({
r: radius2,
x: width/2,
y: height/2,
rank_char: d.Rank_Char,
score_rank: +d.Score_Rank,
univ: d.University,
country: d.Country,
continent: d.Continent
}));
}
Insert cell
simulation2 = d3.forceSimulation()
.force("collide",d3.forceCollide( function(d){
return d.r + 1 }).iterations(20)
)
.force("charge", d3.forceManyBody())
.force("y", d3.forceY().y(height / 100))
.force("x", d3.forceX().x(width2 / 100))
Insert cell
forceStrength2 = 0.80;
Insert cell
centerScale2 = d3.scalePoint().padding(1).range([0, width2]);
Insert cell
Insert cell
Insert cell
chart2 = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width2, height2]);
var circles = svg.selectAll("circle")
.data(mydata, function(d){ return d.ID ;});
const circlesEnter = circles.enter().append("circle")
.attr("r", function(d, i){ return d.r; })
.attr("cx", function(d, i){ return 175 + 25 * i + 2 * i ** 2; })
.attr("cy", function(d, i){ return 250; })
.style("fill", function(d, i){ return colorContinent[d.continent]; })
.style("stroke", function(d, i){ return colorContinent[d.continent];})
.style("stroke-width", 10)
.style("pointer-events", "all")
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
circles = circles.merge(circlesEnter)
function ticked() {
circles
.attr("cx", function(d){ return d.x; })
.attr("cy", function(d){ return d.y; });
}

simulation2
.nodes(mydata)
.on("tick", ticked);
function dragstarted(d,i) {
//console.log("dragstarted " + i)
if (!d3.event.active) simulation2.alpha(1).restart();
d.fx = d.x;
d.fy = d.y;
}

function dragged(d,i) {
//console.log("dragged " + i)
d.fx = d3.event.x;
d.fy = d3.event.y;
}

function dragended(d,i) {
//console.log("dragended " + i)
if (!d3.event.active) simulation2.alphaTarget(0);
d.fx = null;
d.fy = null;
var me = d3.select(this)
//console.log(me.classed("selected"))
me.classed("selected", !me.classed("selected"))
d3.selectAll("circle.selected")
.style("fill", "none")
}
function groupBubbles() {
hideTitles();

// @v4 Reset the 'x' force to draw the bubbles to the center.
simulation2.force('x', d3.forceX().strength(forceStrength2).x(width2/ 2));

// @v4 We can reset the alpha value and restart the simulation
simulation2.alpha(1).restart();
}
function splitBubbles(byVar) {
centerScale2.domain(mydata.map(function(d){ return d[byVar]; }));
if(byVar == "all"){
hideTitles()
} else {
showTitles(byVar, centerScale2);
}
//console.log(mydata.map(function(d, i){ return colorContinent[d.continent] }));
d3.selectAll("circle")
.style("fill", mydata.map(function(d, i){ return colorContinent[d.continent] }))
// @v4 Reset the 'x' force to draw the bubbles to their year centers
simulation2.force('x', d3.forceX().strength(forceStrength2).x(function(d){
return centerScale2(d[byVar]);
}));

// @v4 We can reset the alpha value and restart the simulation
simulation2.alpha(2).restart();
}
function hideTitles() {
svg.selectAll('.title').remove();
}

function showTitles(byVar, scale) {
// Another way to do this would be to create
// the year texts once and then just hide them.
var titles = svg.selectAll('.title')
.data(scale.domain());
titles.enter().append('text')
.attr('class', 'title')
.merge(titles)
.attr('x', function (d) { return scale(d); })
.attr('y', 40)
.attr('text-anchor', 'middle')
.text(function (d) { return byVar + ' ' + d; });
titles.exit().remove()
}
//console.log(sort2)
splitBubbles(sort2);
return svg.node();
}
Insert cell
Insert cell
Insert cell
import {slider,button,select,text,radio,checkbox,number} from "@jashkenas/inputs"
Insert cell
d3 = require("d3@v5")
Insert cell
colorContinent = ({Europe: "#F45656", Asia: "#EAEA34", "North America": "#3EA5DD", "Oceania" : "#2E3842", "Africa" : "blue", "South America": "pink"})
Insert cell
width = 960
Insert cell
height = 500;
Insert cell
height2 =1000;
Insert cell
width2 = 1500;
Insert cell
radius = 25;
Insert cell
radius2 = 2;
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