fix(core): repaint feature-state-driven symbol paint properties (#4445)

This commit is contained in:
Brandon Roeder
2026-08-04 11:17:53 -05:00
committed by GitHub
parent 5e6fd6bb78
commit a34723ff4a
6 changed files with 122 additions and 0 deletions

View File

@@ -29,6 +29,7 @@
### 🐞 Bug fixes
- *...Add new stuff here...*
- [core] Repaint data-driven symbol paint properties after feature-state updates.
- [core] Accept alpha values in legacy comma-separated `hsl()` colors ([#4434](https://github.com/maplibre/maplibre-native/issues/4434)).
- [core] Fix thread-unsafe headless OpenGL display singleton initialization [#4332](https://github.com/maplibre/maplibre-native/pull/4332)
- [macos] Fix `mlt-cpp` and `mbgl-vendor-icu` not being included in the amalgamation

Binary file not shown.

After

Width:  |  Height:  |  Size: 616 B

View File

@@ -0,0 +1,106 @@
{
"version": 8,
"metadata": {
"test": {
"width": 64,
"height": 64,
"operations": [
[
"wait"
],
[
"setFeatureState",
{
"source": "geojson",
"id": "red"
},
{
"color": "red"
}
],
[
"wait"
]
]
}
},
"zoom": 2,
"sprite": "local://sprites/sprite",
"glyphs": "local://glyphs/{fontstack}/{range}.pbf",
"sources": {
"geojson": {
"type": "geojson",
"data": {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"id": "red",
"geometry": {
"type": "Point",
"coordinates": [
0,
0
]
},
"properties": {
"label": "R"
}
}
]
}
}
},
"layers": [
{
"id": "background",
"type": "background",
"paint": {
"background-color": "white"
}
},
{
"id": "symbol",
"type": "symbol",
"source": "geojson",
"layout": {
"icon-image": "dot.sdf",
"icon-allow-overlap": true,
"icon-ignore-placement": true,
"text-field": [
"get",
"label"
],
"text-font": [
"Open Sans Semibold",
"Arial Unicode MS Bold"
],
"text-size": 14,
"text-offset": [
0,
1.5
],
"text-allow-overlap": true,
"text-ignore-placement": true
},
"paint": {
"icon-color": [
"coalesce",
[
"feature-state",
"color"
],
"black"
],
"text-color": [
"coalesce",
[
"feature-state",
"color"
],
"black"
]
}
}
]
}

View File

@@ -35,3 +35,5 @@ Tapping a state toggles its `selected` feature-state key and shows a toast:
- Use `getFeatureState()` on the source to inspect the current state for one feature.
- Use `removeFeatureState()` or `resetFeatureStates()` on the source to clear state.
- For `VectorSource`, all feature-state methods require a `sourceLayerId` parameter.
- Feature-state expressions update paint properties, including symbol paint properties such as `icon-color`, `icon-opacity`, `text-color`, and `text-opacity`.
- Feature-state expressions are not supported in layout properties such as `icon-image` or `text-field`.

View File

@@ -96,6 +96,18 @@ bool SymbolBucket::hasData() const {
hasTextCollisionBoxData() || hasIconCollisionCircleData() || hasTextCollisionCircleData();
}
void SymbolBucket::update(const FeatureStates& states,
const GeometryTileLayer& layer,
const std::string& layerID,
const ImagePositions& imagePositions) {
auto it = paintProperties.find(layerID);
if (it != paintProperties.end()) {
it->second.iconBinders.updateVertexVectors(states, layer, imagePositions);
it->second.textBinders.updateVertexVectors(states, layer, imagePositions);
uploaded = false;
}
}
bool SymbolBucket::hasTextData() const {
return !text.segments.empty();
}

View File

@@ -228,6 +228,7 @@ public:
void upload(gfx::UploadPass&) override;
bool hasData() const override;
void update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) override;
std::pair<uint32_t, bool> registerAtCrossTileIndex(CrossTileSymbolLayerIndex&, const RenderTile&) override;
void place(Placement&, const BucketPlacementData&, std::set<uint32_t>&) override;
void updateVertices(