Public
Edited
May 10, 2023
1 fork
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
viewof show = Inputs.radio(['gdp', 'population'], {label: "Show which values?", value: "gdp"})
Insert cell
allCities = {
//worldMap.attr("style", "background-color:#23548A;");
worldMap.select("#cities").remove()
worldMap.select("#names").remove()
// worldMap.select("#land").attr("fill", "#d8d8d8");

const simulation = d3
.forceSimulation(computedPopns)
.force(
"x",
d3.forceX((d) => mapProjection([d.Longitude, d.Latitude])[0])
)
.force(
"y",
d3.forceY((d) => mapProjection([d.Longitude, d.Latitude])[1])
)
.force(
"collide",
d3.forceCollide(radius*repulsionFactor).strength(0.5)
)


const nodeG = worldMap.append("g")
.attr("id", "cities")
.selectAll("g")
.data(computedPopns)
.join("g")
.call(drag(simulation));

// nodeG.append('circle')
// .attr("r", d => radiusScale(d[d["plotOrder"][2]]));

// nodeG.append("g")
// .each(function(node) {
// for (let i in node["plotOrder"]) {
// let year = node["plotOrder"][i];
// d3.select(this).append("g")
// .append("circle")
// .attr("r", d => radiusScale(d[year]))
// .attr("fill", yearScale(year));
// }
// })

if (show==="Comparison"){
nodeG.append('circle')
.attr("r", radius)//(d) => radiusScale(d[d["plotOrder"][0]])
.attr("fill", "none");
nodeG.append("g")
.each(function(node, i) {
let symbol = d3.select(this).append("g");
let pPlotOrder = node['popnPlotOrder'];
let gPlotOrder = node['gdpPlotOrder'];
symbol.append("clipPath")
.attr("id", "left-clip_" + i)
.append("rect")
.attr("width", radius)
.attr("height", radius * 2)
.attr("x", -radius)
.attr("y", -radius);
for (let i = 0; i < pPlotOrder.length; i+=1) {
let prop = pPlotOrder[i];
symbol
.append("circle")
.attr("cx", 0)
.attr("cy", 0)
.attr("r", d => popnScale(d[prop]))
.attr("clip-path", "url(#left-clip_" + i + ")")
.style("fill", (d) => { console.log(pColor[prop]); return pColor[prop];});
}
symbol.append("clipPath")
.attr("id", "right-clip_" + i)
.append("rect")
.attr("width", radius)
.attr("height", radius * 2)
.attr("x", 0)
.attr("y", -radius);
for (let i = 0; i < gPlotOrder.length; i+=1) {
let prop = gPlotOrder[i];
symbol
.append("circle")
.attr("cx", 0)
.attr("cy", 0)
.attr("r", d => { console.log(gdpScale(d[prop])); return gdpScale(d[prop]);})
.attr("clip-path", "url(#right-clip_" + i + ")")
.style("fill", (d) => { console.log(gColor[prop]); return gColor[prop];});
}
})
} else {
let nodeProp;
let nodeScale;
let nodeColor;
if (show==="gdp") {
nodeProp = 'gdpPlotOrder';
nodeScale = gdpScale;
nodeColor = gColor;
} else {
nodeProp = 'popnPlotOrder';
nodeScale = popnScale;
nodeColor = pColor;
}
nodeG.append("g")
.each(function(node, i) {
let symbol = d3.select(this).append("g");
// let pPlotOrder = node['popnPlotOrder'];
let plotOrder = node[nodeProp];

// symbol.append("clipPath")
// .attr("id", "right-clip_" + i)
// .append("rect")
// .attr("width", radius)
// .attr("height", radius * 2)
// .attr("x", 0)
// .attr("y", -radius);
for (let i = 0; i < plotOrder.length; i+=1) {
let prop = plotOrder[i];
symbol
.append("circle")
.attr("cx", 0)
.attr("cy", 0)
.attr("r", d => { console.log(nodeScale(d[prop])); return nodeScale(d[prop]);})
.attr("clip-path", "url(#right-clip_" + i + ")")
.style("fill", (d) => { console.log(nodeColor[prop]); return nodeColor[prop];});
}
})
}

simulation.on("tick", () => {
nodeG.attr("transform", d => `translate(${d.x}, ${d.y})`)});
invalidation.then(() => simulation.stop());

// worldMap.append("g")
// .attr("id", "names")
// .selectAll("text")
// .data(topCities)
// .join("text")
// .attr("transform", d => `translate(${mapProjection([d["Longitude"], d["Latitude"]])})`)
// .attr("font-size", "0.4em")
// .attr("font-family", "Akkurat LL")
// .attr("fill", "white")
// .attr("stroke", "#063249")
// .attr("stroke-width", "0.1px")
// .attr("paint-order", "stroke")
// .text(d => d["Urban Agglomeration"]);
return worldMap.node();
}
Insert cell
Insert cell
popn = ['urban_2019', 'urban_2050_a']
Insert cell
gdp = ['gdp_urban_2019', 'gdp_urban_2050_a']
Insert cell
selectedPopns[0]
Insert cell
Insert cell
d3
.select(test)
.select('[aria-description="GDP per capita (USD) →"]')
.enter()
.selectAll("text")
.each(function (d) {
// d is the tick's value (in this case, a number)
d3.select(this)
.attr('font-family', 'Helvetica Neue')
.attr("fill", 'black')
.attr("font-size", 10);
})
Insert cell
test2 = Plot.plot({
inset: 8,
grid: true,
width: width*1.25,
height: 1000,
marginLeft: 50, // space to the left of the chart
marginBottom: 50, // space below the chart
color: {
legend: true,
},
facet: {
data: baseData,
x: "continent"
},
x: {
// label: "GDP per capita (USD) →",
tickFormat: "~s",
type: "log",
ticks: 3
},
y: {
// label: "↑ Population (people)",
type: "log",
tickFormat: "~s",
// textColor: "white",
ticks: 5
},
marks: [
//dots
// Plot.dot(baseData, {x: "gdp_capita_2019", y: "urban_2019", text: "iso3", stroke: "continent", strokeWidth: 1,
// //fill:"white", r: 10}),
// }),
// Plot.dot(data_gdpc, {x: "gdp_capita_2050", y: "urban_2050_a", text: "iso3", stroke: "continent"}),
//links
Plot.link(baseData, {
x1: "gdp_capita_2019",
y1: "urban_2019",
x2: "gdp_capita_2050",
y2: "urban_2050_a",
stroke: "continent",
markerEnd: "arrow",
opacity: 0.4,
strokeWidth: 2,
}),
//text
Plot.text(baseData.slice(0, 150), {x: "gdp_capita_2019", y: "urban_2019", text: "city",
fill: "continent",
stroke: "white",
opacity: 0.8,
fontSize: 12}),
// Plot.text(baseData, {x: "gdp_capita_2050", y: "urban_2050_a", text: "city",
// fill: "continent",
// // stroke: "white",
// opacity: 0.8,
// fontSize: 11}),
]
})
Insert cell
test3 = Plot.plot({
inset: 8,
grid: true,
width: 750,
height: 750,
marginLeft: 50, // space to the left of the chart
marginBottom: 50, // space below the chart
color: {
legend: true,
},
// facet: {
// data: baseData,
// x: "continent"
// },
x: {
// label: "GDP per capita (USD) →",
tickFormat: "~s",
type: "log",
ticks: 3
},
y: {
// label: "↑ Population (people)",
type: "log",
tickFormat: "~s",
// textColor: "white",
ticks: 5
},
marks: [
//dots
Plot.dot(baseData, {x: "gdp_capita_2019", y: "urban_2019", text: "iso3", stroke: "continent"}),
// Plot.dot(data_gdpc, {x: "gdp_capita_2050", y: "urban_2050_a", text: "iso3", stroke: "continent"}),
//text
Plot.text(baseData, {x: "gdp_capita_2019", y: "urban_2019", text: "city", font: "IBM Plex Sans",
fill: "continent",
stroke: "white",
opacity: 1,
fontSize: 12}),
// Plot.text(baseData, {x: "gdp_capita_2050", y: "urban_2050_a", text: "city",
// fill: "continent",
// // stroke: "white",
// opacity: 0.8,
// fontSize: 11}),
//links
Plot.link(baseData, {
x1: "gdp_capita_2019",
y1: "urban_2019",
x2: "gdp_capita_2050",
y2: "urban_2050_a",
stroke: "continent",
markerEnd: "arrow",
strokeWidth: 1.5,
opacity: 0.5
}),
]
})
Insert cell
baseData[0]
Insert cell
test = Plot.plot({
inset: 8,
grid: true,
width: width*1.25,
height: 750,
marginLeft: 50, // space to the left of the chart
marginBottom: 50, // space below the chart
color: {
legend: true,
},
facet: {
data: baseData,
x: "continent"
},
x: {
// label: "GDP per capita (USD) →",
tickFormat: "~s",
type: "log",
ticks: 3
},
y: {
// label: "↑ Population (people)",
type: "log",
tickFormat: "~s",
// textColor: "white",
ticks: 5
},
marks: [
//dots
// Plot.dot(data_gdpc, {x: "gdp_capita_2019", y: "urban_2019", text: "iso3", stroke: "continent"}),
// Plot.dot(data_gdpc, {x: "gdp_capita_2050", y: "urban_2050_a", text: "iso3", stroke: "continent"}),
//text
Plot.text(baseData, {x: "gdp_capita_2019", y: "urban_2019", text: "city",
fill: "continent",
// stroke: "white",
opacity: 0.8,
fontSize: 11}),
Plot.text(baseData, {x: "gdp_capita_2050", y: "urban_2050_a", text: "city",
fill: "continent",
// stroke: "white",
opacity: 0.8,
fontSize: 11}),
//links
Plot.link(baseData, {
x1: "gdp_capita_2019",
y1: "urban_2019",
x2: "gdp_capita_2050",
y2: "urban_2050_a",
stroke: "continent",
markerEnd: "arrow",
opacity: 0.3
}),
]
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
pColor = ({'urban_2019': "#A2D6F9", 'urban_2050_a': "#2D76F0"})
Insert cell
gColor = ({'gdp_urban_2019': "#f6aa1c", 'gdp_urban_2050_a': "#bc3908"})

Insert cell
Insert cell
Insert cell
popnScale = d3.scaleLinear().domain(popnDomain).range(radiusRange);
Insert cell
gdpScale = d3.scaleLinear().domain(gdpDomain).range(radiusRange);
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
selectedPopns[0]
Insert cell
computedPopns = {
let popns = []
for (let i in selectedPopns){
let row = selectedPopns[i];
let gdpGap = row['gdp_urban_2050_a'] - row['gdp_urban_2019'];
let popnGap = row['urban_2050_a'] - row['urban_2019'];
row['gdpGap'] = gdpGap;
row['popnGap'] = popnGap;
popns.push(row);
}
return popns;
}
Insert cell
Insert cell
Insert cell
baseData = FileAttachment("urban-data-growth-gdpc-full@2.csv").csv()
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
import {slider} from "@jashkenas/inputs"
Insert cell
import {Swatches} from "@d3/color-legend"
Insert cell
import {mapProjection, activeColorScheme, worldMap} from "b3a0a78984d6df2e"
Insert cell
import {rangeSlider} from '@mootari/range-slider'
Insert cell
viewof range = Inputs.range([0, 100], {label: "Amount", step: 1})
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