The pre-warm was repainting the borders it was only supposed to warm
Found by reading addRegionsLayer while checking exp-shepherd's copy of this fix, not by anything that failed. My pre-warm called paintRegionScope(map.value, []) — the CLEARED look: flat grey borders at width 0.6. The layer does not start there. useMapLayers adds regions-border with line-color set to the REGION-COLOURED match expression and line-width 1, so the moment the Regions tab was first opened, every border turned grey and thinner than the layer had defined. Nothing was going to catch it. The shader compile moved as intended, the write count was unaffected, the highlight still worked, and the checks in flight were a timing measurement and a write count — a change of appearance is invisible to both. It would have been found by a person looking at the map, eventually, and blamed on something else. prewarmRegionPaint reads each property back and re-writes it wrapped in a case whose two branches are the value it already had. The appearance is preserved exactly as the layer defined it, and the property still becomes data-driven, which is all the shader variant depends on. A property the layer does not define is skipped rather than invented, and one already wrapped is left alone so a second call cannot nest cases. paintRegionScope keeps its idle values for the CLEAR path, which is a different thing from the initial state and always was — conflating the two is what caused this. Verified: gates:pre 13/13. Chained on 196eca13. Needs eyes: rega — on the first visit to the Regions tab, the country borders should be REGION-COLOURED at their original width, not grey.
This commit is contained in:
parent
35955a4db6
commit
f83b3a195d
1 changed files with 34 additions and 3 deletions
|
|
@ -1111,6 +1111,26 @@ function _buildFlatLegendMatchExpr(node, legendType) {
|
|||
const REGION_IDLE_FILL = ['case', ['has', 'iso_3166_1_alpha_3'], 0.7, 0.7]
|
||||
const REGION_IDLE_COLOR = ['case', ['has', 'iso_3166_1_alpha_3'], 'rgba(60,60,80,0.35)', 'rgba(60,60,80,0.35)']
|
||||
const REGION_IDLE_WIDTH = ['case', ['has', 'iso_3166_1_alpha_3'], 0.6, 0.6]
|
||||
// Make the region paints data-driven WITHOUT changing what they show: each property is read back and
|
||||
// re-written wrapped in a case whose two branches are the value it already had. A property the layer
|
||||
// does not define is skipped rather than invented, and one already wrapped is left alone.
|
||||
function prewarmRegionPaint(m) {
|
||||
if (!m || !m.getLayer('regions-fill')) return
|
||||
const wrap = (v) => ['case', ['has', 'iso_3166_1_alpha_3'], v, v]
|
||||
const warm = (layer, prop) => {
|
||||
if (!m.getLayer(layer)) return
|
||||
const cur = m.getPaintProperty(layer, prop)
|
||||
if (cur === undefined || cur === null) return
|
||||
if (Array.isArray(cur) && cur[0] === 'case') return
|
||||
m.setPaintProperty(layer, prop, wrap(cur))
|
||||
}
|
||||
try {
|
||||
warm('regions-fill', 'fill-opacity')
|
||||
warm('regions-border', 'line-color')
|
||||
warm('regions-border', 'line-width')
|
||||
} catch (_) { /* style still loading - the first real paint carries it */ }
|
||||
}
|
||||
|
||||
function paintRegionScope(m, isoCodes) {
|
||||
if (!m || !m.getLayer('regions-fill')) return
|
||||
// ★ CANONICAL FIRST, OR THE COMPARE BELOW IS A LIE (rega, L43: still 9 writes per click, not 3).
|
||||
|
|
@ -1618,9 +1638,20 @@ async function ensureRegionsLoaded() {
|
|||
// ★ PRE-WARM HERE, which is the only moment that helps. These layers are added on first visit
|
||||
// to the Regions tab, and rega measured the first ROW click paying 5.5 s (MapLibre) / 11.1 s
|
||||
// (Mapbox) of shader compile because that click was when their paint first became data-driven.
|
||||
// Painting the idle state through paintRegionScope makes it data-driven from the first draw, so
|
||||
// the variant compiles here — where a 6.4 MB GeoJSON is already loading — instead of mid-gesture.
|
||||
paintRegionScope(map.value, [])
|
||||
// Making the paint data-driven at layer-add moves that compile here, where a 6.4 MB GeoJSON is
|
||||
// already loading, instead of into the middle of a gesture.
|
||||
//
|
||||
// WARNING IT WRAPS WHAT THE LAYER ALREADY PAINTS, and does NOT paint the cleared state. The
|
||||
// first version called paintRegionScope(map.value, []) — the CLEARED look, flat grey borders at
|
||||
// width 0.6. addRegionsLayer does not start there: it sets line-color to the region-coloured
|
||||
// match expression and line-width 1 (useMapLayers). So pre-warming with the cleared values
|
||||
// silently repainted every border grey and thinner the moment the layer appeared — a visible
|
||||
// change nobody asked for, and invisible to both things being measured at the time, a timing
|
||||
// check and a write count.
|
||||
// Reading each property back and re-writing it wrapped in an identical-branch case keeps the
|
||||
// appearance exactly as the layer defined it while still making the property data-driven, which
|
||||
// is all the shader variant depends on.
|
||||
prewarmRegionPaint(map.value)
|
||||
// Hide regions on non-Doxa-Regions tabs so they don't show through.
|
||||
if (map.value.getLayer('regions-fill') && activeTab.value?.id !== 'doxa-regions') {
|
||||
map.value.setLayoutProperty('regions-fill', 'visibility', 'none')
|
||||
|
|
|
|||
Loading…
Reference in a new issue