Releases: eurostat/eurostat-map
Release list
4.10.2
Fixes
- Hovering the max/min stat-value label in a discrete legend now correctly highlights the matching feature on proportional-symbol maps too, not just choropleths. The mouseover handler isolated a single region by id using choropleth-only region-fill logic (
getLegendRegionsSelector/highlightRegions), and mouseout always called the choropleth-onlyunhighlightRegions- neither worked for PS symbols, which live in a separate centroids group and are highlighted via opacity, not fill.
Example (no code changes needed - just upgrade):
eurostatmap
.map('ps')
.psSettings({ classificationMethod: 'threshold', colors, thresholds })
.legend({ maxMin: true, colorLegend: { maxMin: true } }) // hover the max/min labels - now highlights the right circle
.build()pointOfDivergenceLabelsStacked+pointOfDivergenceLabelsAtExtremespositioned the top diverging label further north than the max stat value label, and (independently) sat its label almost flush against the arrow tip whenpointOfDivergenceLabelsAtExtremeswas false. Both labels now use consistent vertical offsets that match the max/min value labels' own centering, with a wider, balanced gap from the arrow tip in the non-extremes case.
4.10.1
New
- Diverging discrete legends (choropleth and proportional-symbol color legends) gained several new styling options, all optional and backward compatible:
showDivergingLine- hide the horizontal divergence line/tick and show only the up/down arrows.divergingLinePadding- control the gap left after the longest legend label when computing the line's length, instead of a fixed 15px.pointOfDivergenceLabelsAtExtremes- position the 2 arrow labels near the top/bottom of the whole scale instead of near the divergence point. UnlessdivergingArrowLengthis explicitly set, the arrows stretch to reach near their own label.pointOfDivergenceLabelsStacked- position the 2 labels above/below their arrowhead (starting at the arrow's x position) instead of beside it, to save horizontal width.
Example:
eurostatmap
.map('ch')
.legend({
pointOfDivergenceLabel: 'Increase|Decrease',
pointOfDivergence: 3,
showDivergingLine: false,
pointOfDivergenceLabelsAtExtremes: true,
pointOfDivergenceLabelsStacked: true,
})
.build()Fixes
- Diverging proportional-symbol color legends (
colorLegend.pointOfDivergence/pointOfDivergenceLabel) didn't reliably render. PS classification called deprecatedpsThresholds()/psClasses()wrappers internally (spamming console warnings on every threshold-based classification), and the PS legend never defaultedpointOfDivergencewhen only the label was set - unlike the choropleth legend, whose own default could itself land on a non-integer class index for odd class counts, silently skipping the divergence line since it's matched by strict equality.
Example (no code changes needed - just upgrade):
eurostatmap
.map('ps')
.psSettings({ classificationMethod: 'threshold', colors, thresholds })
.legend({ colorLegend: { pointOfDivergenceLabel: 'Increase|Decrease' } }) // pointOfDivergence now defaults correctly
.build()-
Custom tooltip
textFunctions readingmap.noDataText_for':'values gotundefinedinstead of the configured no-data text, for both choropleth and proportional-symbol maps. Region hover events calltextFunction(region, layer)with the internal layer object, not the map -noDataText_is map-level state and was never forwarded onto it, unlikestatData. Now forwarded the same way. -
The divergence point's own threshold-value label was always relocated (or removed) to avoid overlapping the horizontal divergence line, even when
showDivergingLine: falseleft no line to overlap. It now stays in its normal place next to its own tick in that case.
4.10.0
New
- Choropleth maps can now mix a small set of categorical exceptions into an otherwise numeric classification, via
categoryFillStyle/categoryText. Useful when a handful of regions have no meaningful numeric value for a metric (e.g. "no railway lines" on a map of electrification rate) but still deserve their own legend entry and colour, instead of being lumped into the generic "no data" class or forced into a second base layer (mixing two base layers, e.g. a categorical layer on top of a choropleth, is rejected - a region can only be classified by one base layer). Regions whose raw stat value matches a configured key get their own fill colour, legend swatch, and tooltip label instead of numeric classification or default no-data treatment.
Example:
eurostatmap
.map('ch')
.categoryFillStyle({ '-': '#cccccc' })
.categoryText({ '-': 'No railway lines' })
.build()4.9.5
Improvements
- The ranked bar chart no longer uses any
em-legend-*CSS classes, including its own >40-region histogram fallback. It's not a legend and never shared markup with one on purpose - the shared class names were an oversight that let legend-targeted stylesheets accidentally (and often incorrectly) restyle the bar chart too, most notably clobbering the per-bar value label's contrast-computed text color. Its elements now use their ownem-ranked-bar-chart-*classes with their own default stylesheet. If you had custom CSS targeting the bar chart viaem-legend-*selectors, update it to the new class names (seesrc/core/decoration/ranked-bar-chart.jsandsrc/css/decoration/ranked-bar-chart.css).
Example:
/* Before (4.9.4 and earlier) - also matched the legend, and could override the
per-bar value label's computed contrast color */
.em-legend-title, .em-legend-label {
fill: #4c4b4b;
}
/* After (4.9.5) - scoped to the bar chart only; leave .em-ranked-bar-chart-value
(or the shared .em-ranked-bar-chart-label base class) alone so its per-bar
contrast color still applies */
.em-ranked-bar-chart-title, .em-ranked-bar-chart-code {
fill: #4c4b4b;
}4.9.4
New
rankedBarChart()now works on proportional-symbol maps, not just choropleth maps. Bars are colored using the map's own color classification (previously only reachable on choropleth layers), falling back to a flat bar color on map/layer types that don't classify regions into colored classes at all.
Example:
eurostatmap
.map('ps')
.encoding('size', { stat: 'symbolSize' })
.encoding('color', { stat: 'symbolColor' })
.rankedBarChart({ countryGroup: 'eu' })
.build()Improvements
- Hovering a bar in the ranked bar chart now highlights only that bar's own region on the map, instead of highlighting every region that shares its color class. No config changes needed - this is automatic.
4.9.3
Breaking Changes
RankedBarChartConfigno longer extendsLegendConfig. It's a genuinely independent element, not a legend sub-feature, and the inheritance pulled in legend-only concepts (noData,maxMin/maxMinLabels,titleFontSize,titlePadding,labelOffsets,shapeWidth,shapePadding,sepLineLength, etc.) that never did anything for the bar chart.RankedBarChartConfignow declares only the fields it actually reads. If you were setting any of those legend-only fields onrankedBarChart(), they had no effect before and can simply be removed.
New
RankedBarChartConfiggainedheight. Without it, the bar list grows with region count - all ~35 EU/EFTA/CC countries at the default row height can end up taller than the map itself. When set, bar height and label font size scale down together proportionally so the chart never exceeds that budget.
Example:
map.rankedBarChart({
svgId: 'my-bar-chart-container',
countryGroup: 'eu',
height: 300, // bars and labels shrink together to fit this budget
})4.9.2
Fixes
rankedBarChartnever rendered when enabled after the map's initial build (e.g. a live "show ranked bar chart" toggle switched on after the map had already finished loading). The lazy first-time build only called.build()on the new bar-chart object, which just sets up its empty container - the actual bar drawing happens in.update(), which is otherwise triggered later by an internal pass tied to stat data resolving, a pass that had already run before the object existed..update()is now called immediately after the lazy build so the bars draw right away.
Example (no code changes needed - just upgrade):
// Enabling rankedBarChart after the map is already built and rendered now works correctly.
map.build()
// ...later, in response to a user toggle...
map.rankedBarChart({ svgId: 'my-bar-chart-container', countryGroup: 'eu' })4.9.0
New
- New independent
rankedBarChartmap element (map.rankedBarChart(config)), for choropleth-classified maps - separate from the legend, not a sub-feature of it: one horizontal bar per region, sorted by value, colored by the region's own class color, labeled with its id and value, in the style of statistical-atlas publications. Bars are right-anchored to a common edge and grow leftward as value increases; the value label is drawn inside the bar (automatically switching between black/white for contrast against the bar's own fill) when it fits, otherwise outside to the left of the bar; the region code sits in a bold-italic column that starts right after the bars' shared edge. Above an internal 40-region threshold, automatically falls back to the histogram distribution view instead of drawing one bar per region. Supportstitle/subtitlelike the legend, and has its ownsvgId/positioning - it can render into a completely separate container/SVG element to the legend's.
Example:
map.rankedBarChart({
svgId: 'my-bar-chart-container',
title: 'GDP per inhabitant',
subtitle: 'EU member states only',
countryGroup: 'eu',
})RankedBarChartConfiggainedcountryGroup, to limit which regions appear in the ranked bar chart to a political grouping:'eu'(27 member states),'euEfta'(+ Iceland, Liechtenstein, Norway, Switzerland), or'euEftaCc'(+ current EU candidate countries). Applied before the 40-region histogram-fallback threshold, so filtering a large dataset down to'eu'can bring it back within the bar-chart limit.
Example:
map.rankedBarChart({ countryGroup: 'euEfta' })4.8.6
Fixes
- Legend hover-highlight interactions on exported/zoomable maps were unintentionally blocked by
onlyApplyOpacityWhileZoomeduntil the user zoomed in. That setting now purely controls the legend box's own background opacity (its documented purpose) and no longer incidentally blocks the swatch hover-to-highlight interaction via a capture-phasestopImmediatePropagation()on legendmouseover.
Example (no code changes needed - just upgrade):
map.legend({ onlyApplyOpacityWhileZoomed: true })
// Hovering a legend swatch now highlights the map immediately, even before zooming in.4.8.5
New
BivariateLegendConfiggainedaxisTitleFontSize, for overriding the axis title font size independently of the legend CSS default.
Example:
map.legend({ axisTitleFontSize: 13 })Improvements
- The legend background box's conditional opacity (
onlyApplyOpacityWhileZoomed) now stays synced with the live zoom state instead of only being applied once, at legend creation. - Bivariate legend option changes made via a live
.legend()call are now correctly honoured on the next redraw -annotationOffsets,annotationLineEndOffsetsandnoDataYOffsetwere previously only checked against the initial config, so a later.legend({...})update with these fields could get silently overridden by rotation-dependent defaults. - Bivariate legend x-axis break labels no longer sit on top of their tick marks - label position now accounts for
tickLength.
Fixes
- Overseas inset scalebars (
'image','eu','euEfta'presets) never rendered. These built-in presets set scalebars via the deprecated flat fields (showScalebar,scalebarPosition, etc.), but the scalebar renderer only reads the modern nestedscalebarconfig - soscalebar_stayed unset and nothing drew. Legacy flat scalebar fields on any inset config (built-in presets or your own) are now normalized ontoscalebarautomatically.
Example (no code changes needed - just upgrade):
eurostatmap.map('choropleth').insets('image').build()
// Every overseas inset (Guadeloupe, Réunion, Malta, etc.) now shows its scalebar again.Breaking Changes
BivariateLegendConfig'sannotationLineEndOffsetis renamed toannotationLineEndOffsets, for naming consistency with the other per-corner offset options.BivariateLegendConfig's deprecatedannotationPaddingoption is removed. UseannotationOffsets/annotationLineEndOffsetsinstead.
Example:
map.legend({ annotationLineEndOffsets: { x: 2, y: -2 } })