Public
Edited
May 7
8 stars
Insert cell
Insert cell
Insert cell
Insert cell
<style>
/* Region fill */
.em-cntrg, .em-nutsrg, .em-grid-cell {fill:#efefef !important}
/* borders */
.em-cntbn,
.em-worldbn,
g#em-cntbn > .em-bn-oth:not(.em-bn-co):not(.em-bn-cc):not(.em-bn-eu):not(.em-bn-efta) {
stroke-width: 0.3px !important;
stroke: #000 !important;
}
/* borders */
.em-bn-1, .em-bn-2, .em-bn-3, .em-nutsrg [lvl='3'], .em-nutsrg [lvl='2'], .em-nutsrg [lvl='1'] {
stroke-width: 0px !important;
stroke: #ffffff !important;
}
</style>
Insert cell
eurostatmap
.map("spark")
.svgId("sparklineSVG")
.nutsLvl(2)
.width(width)
.nutsYear(2021)
.title("Population change 2009 - 2023")
.subtitle("Crude rate of total population change")
//.zoomExtent([1, 2]) //pan & zoom
.statSpark(
{
eurostatDatasetCode: "demo_r_gind3",
filters: { indic_de: "GROWRT" },
unitText: "Population change"
},
[
"2009",
"2010",
"2011",
"2012",
"2013",
"2014",
"2015",
"2016",
"2017",
"2018",
"2019",
"2020",
"2021",
"2022",
"2023"
], //dates
[
"2009",
"2010",
"2011",
"2012",
"2013",
"2014",
"2015",
"2016",
"2017",
"2018",
"2019",
"2020",
"2021",
"2022",
"2023"
] //labels
)
.sparkType("line")
.sparkLineWidth(30)
.sparkLineStrokeWidth(1.3)
.sparkLineColor((d, i) => {
const trend = populationTrend(d);

if (trend === "decreased") return "#ff4444";
if (trend === "no change") return "#f9a4a4"; // Or pick another color for stability
if (trend === "increased") return "#0083ff";

// Optional fallback
return "#b5cbff";
})
.sparkLineHeight(5)
.sparkLineOpacity(1)
.sparkLineCircleRadius(0)

//map styling
.nutsbnStroke({
0: "black",
1: "grey",
2: "grey",
3: "grey",
oth: "black",
co: "black"
})
.nutsbnStrokeWidth({ 0: 0.2, 1: 0.1, 2: 0, 3: 0, oth: 0.1, co: 0.2 })
.tooltip({
xOffset: 30,
yOffset: 150,
fontSize: "12px",
maxWidth: Math.min(400, window.innerWidth)
})
.sparkTooltipChart({
width: 150,
height: 50,
margin: { left: 60, right: 40, top: 40, bottom: 40 },
circleRadius: 0
})
.build()
Insert cell
function populationTrend(data) {
if (!Array.isArray(data) || data.length === 0) {
throw new Error("Input must be a non-empty array");
}

let total = 1;
data.forEach((d) => {
if (typeof d.value !== "number") {
throw new Error('Each item must have a numeric "value" property');
}
total *= 1 + d.value / 100;
});

if (total > 1) {
return "increased";
} else if (total < 1) {
return "decreased";
} else {
return "no change";
}
}
Insert cell
eurostatmap = require("eurostat-map@4.1.55")
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