Published
Edited
Jun 27, 2020
Insert cell
Insert cell
Insert cell
data = {
const text = await FileAttachment("univ_agg_with_continent.csv").text();
return d3.csvParse(text, (d) => ({
r: radius2,
x: width/2,
y: height2/2,
rank_char: d.Rank_Char,
score_rank: +d.Score_Rank,
univ: d.University,
country: d.Country,
continent: d.Continent
}));
}
Insert cell
simulation = d3.forceSimulation()
.force("collide",d3.forceCollide( function(d){
return d.r + 1 }).iterations(20)
)
.force("charge", d3.forceManyBody())
.force("y", d3.forceY().y(height2 / 100))
.force("x", d3.forceX().x(width / 100))
Insert cell
forceStrength = 0.6;
Insert cell
centerScale = d3.scalePoint().padding(1).range([0, height2]);
Insert cell
uniqueUniv = [...new Set(data.map(item => item.univ))];
Insert cell
uniqueCountries = [...new Set(data.map(item => item.country))];
Insert cell
uniqueContinent = [...new Set(data.map(item => item.continent))];
Insert cell
univScale = d3.scaleBand()
.domain(data.map(d=>d.univ))
.range([0,100])
Insert cell
countryScale = d3.scaleBand()
.domain(uniqueCountries)
.range([0,100])
Insert cell
continentScale = d3.scaleBand()
.domain(uniqueContinent)
.range([0,100])
Insert cell
colorJson = ({univ: univScale, country: countryScale, continent: continentScale})
Insert cell
d3.interpolateSpectral(colorJson["country"]("United States"))
Insert cell
univColors = data.map(function(d){return "#F45656"})
Insert cell
countryColors = data.map(function(d){return d3.interpolateRainbow(colorJson["country"](d.country))})
Insert cell
continentColors = data.map(function(d){return d3.interpolateRainbow(colorJson["continent"](d.continent))})
Insert cell
univColorMap = Object.assign(...uniqueUniv.map((k, i) => ({[k]: univColors[i]})))
Insert cell
countryColorMap = Object.assign(...uniqueCountries.map((k, i) => ({[k]: countryColors[i]})))
Insert cell
colorMap = ({univ: univColorMap, country: countryColorMap, continent: colorContinent})
Insert cell
d3.interpolateSpectral(countryScale("United Kingdom"))
Insert cell
html`<div style="width: 100px; height: 100px; background-color: ${d3.interpolateSpectral(countryScale("Philippines"))};"></div>`
Insert cell
Insert cell
Insert cell
chart = {
const svg = d3.create("svg")
.classed("chart_svg", true)
.attr("viewBox", [0, 0, width, height2]);
var circles = svg.selectAll("circle")
.data(data, function(d){ return d ;});
const circlesEnter = circles.enter().append("circle")
.attr("r", function(d, i){ return d.r; })
.attr("cx", function(d, i){ return 250 })
.attr("cy", function(d, i){ return 175 + 25 * i + 2 * i ** 2; })
.style("fill", function(d, i){ return "#F45656";})
.style("stroke", function(d, i){ return "#F45656";})
.style("stroke-width", 10)
.style("pointer-events", "all")
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
circles = circles.merge(circlesEnter)

var titles = svg.selectAll('.title')
.data(centerScale.domain());
// console.log(colorJson["univ"](data.map(function(d){ return d.univ; })))
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.selected")
.style("fill", "none")

}

function groupBubbles() {
hideTitles();

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

// @v4 We can reset the alpha value and restart the simulation
simulation.alpha(1).restart();
}
return svg.node();
}
Insert cell
function splitBubbles(byVar) {

centerScale.domain(data.map(function(d){ return d[byVar]; }));

if(byVar == "univ"){
hideTitles()
} else {
showTitles(byVar, centerScale);
}

console.log(d3.selectAll("circle").attr("stroke", data.map(function(d,i) {
return "blue"})))
d3.selectAll("circle")
.style("fill", function(d, i){ return colorMap[byVar][d[byVar]];})
.style("stroke", function(d, i){ return colorMap[byVar][d[byVar]];})

// @v4 Reset the 'x' force to draw the bubbles to their year centers
simulation.force('y', d3.forceY().strength(forceStrength).y(function(d){
return centerScale(d[byVar]);

}));

// @v4 We can reset the alpha value and restart the simulation
simulation.alpha(2).restart();
}
Insert cell

function hideTitles() {
const svg = d3.select("svg")
svg.selectAll('.title').remove();
}
Insert cell
function showTitles(byVar, scale) {
// Another way to do this would be to create
// the year texts once and then just hide them.
const svg = d3.select("chart_svg")
var titles = svg.selectAll('.title')
.data(scale.domain());

titles.enter().append('text')
.attr('class', 'title')
.merge(titles)
.attr('x', 340)
.attr('y', function (d) {console.log(scale(d)); return scale(d);})
.attr('text-anchor', 'middle')
.text(function (d) { return byVar + ' ' + d; });

titles.exit().remove()
}
Insert cell
splitBubbles(radio_button_input);
Insert cell
Insert cell
Insert cell
import {slider,button,select,text,radio,checkbox,number} from "@jashkenas/inputs"
Insert cell
d3 = require("d3@v5", "d3-interpolate@1")
Insert cell
colorContinent = ({Europe: "#F45656", Asia: "#EAEA34", "North America": "#3EA5DD", "Oceania" : "#2E3842", "Africa" : "blue", "South America": "pink"})
Insert cell
height2 =1500;
Insert cell
width = 1500;
Insert cell
radius = 25;
Insert cell
radius2 = 2;
Insert cell
// color = d3.scaleOrdinal(d3.schemeTableau10);
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