Published
Edited
Jan 12, 2021
2 stars
Insert cell
Insert cell
chart = {
const root = treemap(data);

const svg = d3
.create("svg")
.attr("viewBox", [0, 0, width, height])
.style("font", "10px sans-serif");

const leaf = svg
.selectAll("g")
.data(root.leaves())
.join("g")
.attr("transform", d => `translate(${d.x0},${d.y0})`);

leaf.append("title").text(
d =>
`${d
.ancestors()
.reverse()
.map(d => d.data.name)
.join("/")}\n${format(d.value)}`
);

leaf
.append("rect")
.attr("id", d => (d.leafUid = DOM.uid("leaf")).id)
.attr("fill", d => {
while (d.depth > 1) d = d.parent;
console.log(d);
if (d.data.name == 'Kolinda') return '#1375b7';
//
else return '#c93135';
// return color(d.data.name);
})
.attr("fill-opacity", 0.6)
.attr("width", d => d.x1 - d.x0)
.attr("height", d => d.y1 - d.y0);

leaf
.append("clipPath")
.attr("id", d => (d.clipUid = DOM.uid("clip")).id)
.append("use")
.attr("xlink:href", d => d.leafUid.href);

leaf
.append("text")
.attr("clip-path", d => d.clipUid)
.selectAll("tspan")
.data(d =>
d.data.name
.split(/(?=[A-Z][a-z])|\s+/g)
.concat(format(Math.pow(d.value, 2)))
)
.join("tspan")
.attr("x", 3)
.attr(
"y",
(d, i, nodes) => `${(i === nodes.length - 1) * 0.3 + 1.1 + i * 0.9}em`
)
.attr("fill-opacity", (d, i, nodes) =>
i === nodes.length - 1 ? 0.7 : null
)
.text(d => d);

// svg.selectAll('g').attr('transform', null);

svg
.selectAll('g')
.transition()
.duration(3000)
.delay(4000)
.attr('transform', null)
//.attr('width', d => d.data.centroid[0])
// .attr('x', d => d.data.centroid[0])
// .attr('y', d => d.data.centroid[1]);
.attr(
'transform',
(d, i) =>
`translate(${d.data.centroid[0]},${d.data.centroid[1]})scale(0.4)`
);
// .attr('id', (d, i) => console.log(d.data))
// .attr('fill', 'green');

return svg.node();
}
Insert cell
format = d3.format(",d")
Insert cell
treemap = data =>
d3
.treemap()
.tile(d3.treemapSquarify)
.size([width, height])
.padding(1)
.round(true)(
d3
.hierarchy(data)
.sum(d => d.value)
.sort((a, b) => b.value - a.value)
)
Insert cell
data = {
var retval = Object.assign({ name: '2020' }, { children: new Array() });

var kgk = Object.assign({ name: 'Kolinda' }, { children: new Array() });
var zoky = Object.assign({ name: 'Zoki' }, { children: new Array() });

municipalities.forEach(opcina => {
let votes = Math.abs(opcina.properties.votes.diff);

votes = d3.scaleSqrt()(votes);
if (opcina.properties.votes.diff < 0)
zoky.children.push({
name: opcina.properties.name,
value: votes,
centroid: opcina.properties.centroid
});
else
kgk.children.push({
name: opcina.properties.name,
value: votes,
centroid: opcina.properties.centroid
});
});

retval.children.push(kgk);
retval.children.push(zoky);

return retval;
}
Insert cell
Insert cell
jlsData = d3.csvParse(await FileAttachment('jls@1.csv').text(), d3.autoType)
Insert cell
municipalities = topojson
.feature(croatia, croatia.objects.hrvatska)
.features.map(municipality => {
const { population } = populations.find(
p => p.id === municipality.properties.ID_2
);

const name = `${municipality.properties.NAME_2}`;
const votingDatum = votingData.find(
d => d.gropNaziv.toUpperCase() == name.toUpperCase()
);

const jlsDatum = jlsData.find(
d => d.jls.toUpperCase() == name.toUpperCase()
);

let kgkWins = true;
if (votingDatum && votingDatum.diff < 0) kgkWins = true;

var diff = 0;
if (votingDatum) diff = votingDatum.diff;
diff = Math.abs(diff);

return {
...municipality,
properties: {
name,
//state: state.properties.name,
votes: { ...votingDatum },
jls: { ...jlsDatum },
population,
// density: population / municipality.properties.ALAND * 1e6,
centroid: projection(
turf.centroid(municipality.geometry).geometry.coordinates
),
radius: radiusScale(diff),
blueWin: kgkWins
// radius: radiusScale(population)
}
};
})
.filter(c => c.properties.centroid)
//.filter(c => c.geometry.type === "MultiPolygon")
.sort((a, b) =>
a.properties.centroid[0] < b.properties.centroid[0] ? -1 : 1
)
.map((d, i) => {
let geometry;
if (d.geometry.type !== "MultiPolygon") {
geometry = d.geometry;
} else {
geometry = {
type: d.geometry.type,
coordinates: d.geometry.coordinates
.sort((a, b) =>
turf.area(turf.polygon(a)) > turf.area(turf.polygon(b)) ? -1 : 1
)
.slice(0, 1)
};
}
return {
...d,
rank: i,
geometry
};
})
Insert cell
Insert cell
Insert cell
projection = d3
.geoAlbers()
.rotate([-15, 0])
.fitExtent(
[[20, 70], [width * 0.9, height * 0.9]],
topojson.feature(croatia, croatia.objects['hrvatska'])
)
Insert cell
Insert cell
populations.filter(d => d.found == false)
Insert cell
populations = {
let retval = new Array();
croatia.objects.hrvatska.geometries.forEach(opcina => {
let opcinaFound = populationData.find(
d => d.Name.toUpperCase() == opcina.properties.NAME_2.toUpperCase()
);

retval.push({
id: opcina.properties.ID_2,
name: opcina.properties.NAME_2,
found: opcinaFound ? true : false,
population: opcinaFound ? opcinaFound.Population : 0
});
});
return retval;
}
Insert cell
// populations.filter(d => d.found == false)
Insert cell
// glas = izbori.find(d=>d.gropNaziv.toUpperCase()=='Zagreb'.toUpperCase())
Insert cell
izbori = {
let retval = JSON.parse(await FileAttachment("izbori@7.json").text());
return retval;
}
Insert cell
// votingData.filter(d => d.zupNaziv != "" && d.gropNaziv == "")
Insert cell
Insert cell
Insert cell
// stanovnistvo = {
// let retval = d3.csvParse(await FileAttachment("hrvatska.stanovnistvo.2011@4.csv").text(), d3.autoType)
// let zagreb = 0;
// retval.filter(d=>d.county == 'Grad Zagreb').forEach(cetvrt=>{
// zagreb += cetvrt.population;
// })
// retval = retval.filter(d => d.county != 'Grad Zagreb')
// retval.push({
// county: 'Grad Zagreb',
// denomination: 'Grad',
// name: 'Zagreb',
// population: zagreb,
// });
// return retval
// }
Insert cell
populationData = d3.csvParse(
await FileAttachment('stanovnistvo_povrsina@2.csv').text(),
d3.autoType
)
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