ITADN

`{line,fill,circle,..}-layer-opacity` for feature-uniform opacity

#1651OpenCommanderStorm 创建于 2026-05-15
C
CommanderStormcommented
# Design Proposal: `{line,fill,circle,..}-layer-opacity` for feature-uniform opacity ## Motivation Map styles **today** expose opacity primarily as a **feature-level** rendering property, where blending is applied during rasterization and compositing of individual geometries within a layer. This ties visual intensity to feature-by-feature accumulation rather than treating a layer as a single visual unit. In practice, style authors often **need** to control the **opacity of entire layers as cohesive entities**, for example to: - fade thematic layers in or out based on zoom - smoothly transition visibility during storytelling or temporal animation - adjust emphasis without changing intra-layer feature contrast - hiding data-overlaps on transparent fill layers These patterns are currently approximated using workarounds such as layer duplication or feature-level opacity tuning, which do not cleanly separate feature styling from layer-level presentation control. This proposal introduces a missing abstraction: uniform post-compositing control over a layer’s rendered output. Currently, having opacity on lines cannot be done since every feature is rendered by itself. It looks buggy. <img width="400px" src="https://github.com/user-attachments/assets/3df888b0-6e72-4091-ab6c-40dfdea7c4e9" /> ## Proposed Change This proposal introduces a clear separation between: - feature-level styling (how individual geometries are rendered and blended within a layer), and - layer-level compositing (how the fully rendered layer is integrated into the map) `{filll,circle,heatmap,line,symbol,hillshade,color-relief}-layer-opacity` applies a uniform alpha multiplier to the fully composited output of a layer, after feature rendering and before final integration into the framebuffer. This enables treating a layer as a single visual unit, while preserving existing feature-level opacity semantics. The property is orthogonal to existing *-opacity values and supports transitions and Zoom-based expressions. So as a precise spec: > This property applies a **uniform alpha multiplier** to the **fully composited raster result of a single layer**, **after all feature-level opacity blending** and **before integration into the framebuffer**. It does **not affect in- or inter feature oppactity accumulation**. <details><summary>Or visually (click to expand)</summary> <p> ![](https://raw.githubusercontent.com/maplibre/maplibre-style-spec/984da57428135c7c85a11acaa1dcbe46d3839627/docs/assets/fill-layer-opacity.svg) ![](https://raw.githubusercontent.com/maplibre/maplibre-style-spec/984da57428135c7c85a11acaa1dcbe46d3839627/docs/assets/line-layer-opacity.svg) Or in more concrete usecases | using `line-opacity` vs `line-layer-opacity` | |--| | <img width="1406" height="753" alt="image" src="https://github.com/user-attachments/assets/6d45c2fe-c0f3-4610-bbf8-a76c06fd7bec" /> | | `line-opacity` | `line-layer-opacity` | |--------|--------| | <img width="100%" alt="image" src="https://github.com/user-attachments/assets/8540a1c0-e81d-4bb8-8d62-03a9cb08b12d" /> | <img width="100%" alt="image" src="https://github.com/user-attachments/assets/4db9e197-076b-43c1-b96d-51e4f80792c9" /> | See https://github.com/maplibre/maplibre/discussions/503 for more diagrams </p> </details> ## API Modifications Add `{line,fill,circle,..}-layer-opacity`. These properties: - accept values in the range 0..=1 - default to 1 - are transitionable - support zoom expressions - are data-constant (because they interact with an entire layer, data-driven or feature-state would not make sense) ## Migration Plan and Compatibility This is backwards compatible. ## Rejected Alternatives Some alternatives and workarounds discussed include: - continuing to use existing `*-opacity` properties, - rendering layers into intermediate frame buffers manually, - duplicating layers with adjusted negative styling, - or introducing special blending/.. behaviour into existing opacity properties. However, these approaches are either: - visually inconsistent, - inefficient, - difficult to author, - or unable to reproduce true feature-uniform opacity behavior cleanly. Additional discussion and alternative approaches: https://github.com/maplibre/maplibre/discussions/503. Furthermore, we rejected a "bare" `layer-opacity` because while consistent with `resampling` and `visibility`, it is inconsistent with the rest of the `line-*` properties, so adding the prefix is maybe better. ## Implementation roadmap I have PRs are open for: - [x] line https://github.com/maplibre/maplibre-style-spec/pull/1650 https://github.com/maplibre/maplibre-gl-js/pull/7570 - [x] fill https://github.com/maplibre/maplibre-style-spec/pull/1650 https://github.com/maplibre/maplibre-gl-js/pull/7570 - [ ] symbol - [ ] circle - [ ] heatmap - [ ] fill-extrusion - [ ] hillshade - [ ] color-relief - raster - wontfix because semantically equivalent existing properties exist - background - wontfix because semantically equivalent existing properties exist The implementation plan for all layer types is the same as noted above > This property applies a **uniform alpha multiplier** to the **fully composited raster result of a single layer**, **after all feature-level opacity blending** and **before integration into the framebuffer**. It does **not affect in- or inter feature opacity accumulation**.
26 条评论