Skip to content

colorBy + hazard composition

The runtime composes one RGBA DataTexture per tile, indexed by feature_id. The shader does a single texture2D lookup per fragment.

Compositing rule

text
base  = colorBy(attrs)            // always opaque
for each HazardLayer in children order:
  overlay = hazardColor(layer, attrs)
  base.rgb = mix(base.rgb, overlay.rgb, overlay.a)
  base.a   = max(base.a, overlay.a)

Later <HazardLayer> children win visually.

Hazard semantics

conditionresult
covered=falseno overlay — keep colorBy (hazard has no data)
covered=true && depth_max=nullhalf-opacity safe color — surveyed clear
covered=true && depth_max > 0depth ramp at full opacity
covered=true && landslide_in_zone=falsesafe color
covered=true && landslide_in_zone=truewarning color

This avoids the common bug of conflating "no data" with "no risk".

Built-in colorBy

valuesource
'year_built'linear ramp 1900 → 2020
'structure'categorical
'height'linear ramp 0–120 m
'river_flood' | 'inland_flood' | 'tsunami' | 'storm_surge'depth ramp
'landslide'categorical in_zone

You can also pass:

  • { field: 'floors', ramp: { type: 'linear', stops: [...] } } for arbitrary fields.
  • A function (attrs) => Color for fully custom logic. Called only when textures rebuild, never per-frame.

MIT License. PLATEAU data © Project PLATEAU / MLIT — CC BY 4.0.