Published
Edited
Mar 8, 2022
1 fork
2 stars
Insert cell
Insert cell
html`<h1>${ifRussia(chart)}</h1>`
Insert cell
viewof chart = {
const width = 1250;
const height = 810;
let stateselected="none";
let stroke_width_original = 0;
let selected_1 = false;
let selected_2 = false;
let selected_3 = false;
let selected_4 = false;
let selected_5 = false;
const zoom = d3.zoom()
.scaleExtent([1, 8])
.on("zoom", zoomed);

const svg = d3.create("svg")
.attr("viewBox", [0, 0, width+350, height])
.attr("width",width)
.attr("height",height)
.on("click", reset);

const g = svg.append("g");

const color = d3.scaleOrdinal()
.domain(["1. High income: OECD",
"2. High income: nonOECD",
"3. Upper middle income",
"4. Lower middle income",
"5. Low income"])
.range(d3.schemeReds[5]);
//.range(d3.schemeRdBu[5])

var path = d3.geoPath().projection(
d3.geoMercator()
.fitSize([width, height], world));
g.selectAll("path")
.data(world.features, d => d.properties.brk_name)
.enter().append("path")
.attr("d", path);

const countries = g.append("g")
.selectAll("path.countries")
.data(world.features, d => d.properties.brk_name)
.join("path")
.attr("class", "countries")
.attr("fill",d=>color(d.properties.income_grp))
.attr("d", d => path(d))
.attr("stroke", "gray")
.on("click", clicked)
countries.append("title")
.text(d => d.properties.brk_name);
svg.call(zoom);

svg.append("g")
.attr("transform", "translate(750,0)")
.append(() => legend({color, title: "Income Group", width: 400}))
svg.selectAll(".tick")
.on("click", onLegendClick);
function reset() {
countries.transition().style("fill", null);
svg.selectAll(".state_name").remove();
svg.property("value", "none").dispatch("input");
svg.transition().duration(750).call(
zoom.transform,
d3.zoomIdentity,
d3.zoomTransform(svg.node()).invert([width / 2, height / 2])
);
}

function onLegendClick(event, d) {
var value = d3.select(this).text()
if (value == "1. High income: OECD" && !selected_1) {
selected_1 = true;
} else if (value == "1. High income: OECD" && selected_1) {
selected_1 = false;
}
if (value == "2. High income: nonOECD" && !selected_2) {
selected_2 = true;
} else if (value == "2. High income: nonOECD" && selected_2) {
selected_2 = false;
}
if (value == "3. Upper middle income" && !selected_3) {
selected_3 = true;
} else if (value == "3. Upper middle income" && selected_3) {
selected_3 = false;
}
if (value == "4. Lower middle income" && !selected_4) {
selected_4 = true;
} else if (value == "4. Lower middle income" && selected_4) {
selected_4 = false;
}
if (value == "5. Low income" && !selected_5) {
selected_5 = true;
} else if (value == "5. Low income" && selected_5) {
selected_5 = false;
}
// d3.selectAll("path.countries").filter(function(d) {
// return d.properties.income_grp != value;
// }).attr("fill", "gray");
// d3.selectAll("path.countries").attr("fill",function(d) {
// if(d.properties.income_grp!= value) {
// return "gray";
// } else {
// return color(d.properties.income_grp);
// }
// })
var selection = updateSelection(selected_1, selected_2, selected_3, selected_4, selected_5)
console.log(selection);
d3.selectAll("path.countries").attr("fill",function(d) {
//console.log(d)
if(selection.includes(d.properties.brk_name)) {
return color(d.properties.income_grp);
} else {
// check if everythin is false
if (!selected_1 && !selected_2 && !selected_3 && !selected_4 && !selected_5) {
return color(d.properties.income_grp);
} else {
return "gray";
}
}
})
};

function clicked(event, d) {
const [[x0, y0], [x1, y1]] = path.bounds(d);
stateselected = d.properties.brk_name;
console.log(stateselected);
svg.property("value", stateselected).dispatch("input");
event.stopPropagation();
//countries.attr("stroke", "gray");
//countries.attr("stroke-width", stroke_width_original);
//d3.select(this).transition().style("fill", "red");
svg.selectAll(".state_name").remove();
svg.append("text")
.attr("x", 500)
.attr("y", 0)
.style("font-size", "45px")
.text(stateselected)
.attr("class","state_name");
svg.transition().duration(750).call(
zoom.transform,
d3.zoomIdentity
.translate(width / 2, height / 2)
.scale(Math.min(3, 0.9 / Math.max((x1 - x0) / width, (y1 - y0) / height)))
.translate(-(x0 + x1) / 2, -(y0 + y1) / 2),
d3.pointer(event, svg.node())
);
}
function zoomed(event) {
const {transform} = event;
g.attr("transform", transform);
g.attr("stroke-width", 1 / transform.k);
}

svg.property("value", "none").dispatch("input");
return svg.node();
}
Insert cell
Insert cell
function updateSelection(selected_1, selected_2, selected_3, selected_4, selected_5) {
var selected=[""]
if (selected_1) {
var l1 = world.features.filter(function(d) {
return(d.properties.income_grp == "1. High income: OECD")
})
selected = selected.concat(l1.map(d=> d.properties.brk_name))
}
if (selected_2) {
var l2 = world.features.filter(function(d) {
return(d.properties.income_grp == "2. High income: nonOECD")
})
selected=selected.concat(l2.map(d=> d.properties.brk_name))
}
if (selected_3) {
var l3 = world.features.filter(function(d) {
return(d.properties.income_grp == "3. Upper middle income")
})
selected=selected.concat(l3.map(d=> d.properties.brk_name))
}
if (selected_4) {
var l4 = world.features.filter(function(d) {
return(d.properties.income_grp == "4. Lower middle income")
})
selected=selected.concat(l4.map(d=> d.properties.brk_name))
}
if (selected_5) {
var l5 = world.features.filter(function(d) {
return(d.properties.income_grp == "5. Low income")
})
selected=selected.concat(l5.map(d=> d.properties.brk_name))
}
return selected;
}
Insert cell
function ifRussia (value) {
if (value=="Russia")
return "Mother Russia"
else
return value;
}
Insert cell
world= FileAttachment("world-110m.geo.json").json()
Insert cell
FileAttachment("world-110m.json").json()
Insert cell
topojson = require("topojson-client@3")
Insert cell
d3 = require("d3@6","d3-geo@3", "d3-geo-projection@4")
Insert cell
import {select} from "@jashkenas/inputs"
Insert cell
import {legend} from "@d3/color-legend"
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