Mapbox-gl-js: Support for animation/transitions when setting data-driven paint properties

Created on 10 Sep 2016  路  16Comments  路  Source: mapbox/mapbox-gl-js

Up until support arrived for data driven fill-color I generated multiple layers and styled them separately to achieve color reliefs. The data driven approach has allowed me to go from hundreds of layers to one, which is great!

One visual effect that I lost, however, is that when I used to change color on my previous individual layers with discrete fill-color values I got a subtle fading effect, which was quite nice.

Now, when updating the data-driven property with new stops/colors, the change is much more disruptive and some polygons are even non-visible for a short instant.

I understand that transitioning from one data-driven setting to another is a bit more complicated than doing so between two discrete values. I believe, however, that this should be possible in principle.

Have you discussed having data-driven properties transition smoothly as well?

cross-platform feature

Most helpful comment

@mayteio hey, if you think this is so easy to implement, please welcome to do so and submit a PR.

All 16 comments

@averas I had the same question a few days back-- turns out we don't support transitions in DDS properties yet. Good feature enhancement down the road, though

cc/ @lucaswoj

How can one implement this feature?

I understand that the transition happen smoothly because updating the layer color happens directly on main thread, the source doesn't get reloaded (the feature constant stuff in the update method).

Changing the fill-color stops is expensive because the whole source gets reloaded. The change of color is actually happening on worker and not main thread. Can anybody give some guidelines to implement this, I might make PR if I come up with something?

@mourner

@sanjin-saric To implement this feature one would need to modify GL JS such that

  • it retains old vertex buffers during a paint transition
  • it binds both the new and old vertex buffers while rendering the paint transition
  • it interpolates between the new and old vertex buffer values while rendering the paint transition

We would be very grateful for a PR that implements this feature. I suggest starting with an issue labeled starter task to get the hang of the codebase and PR workflow before diving in.

@lucaswoj
I am quite familiar with the codebase. Thats not a problem.

I have an issue with these steps. Have you considered performance side of things?

Imagine a scenario:

  1. I change the colors -> 2. the request goes to workers so the new bucket is calculated (while old one is retained) -> 3. old and new vertex buffers return to main thread -> 4. drawFill uses those buckets to transition between colors.

If there are a lot of features, there could be a considerable amount of time until step 4. happens. Wouldn't that result in laggy transition?

Correct. This approach necessitates delay while buffers are populated before the transition can begin.

Well isn't this an issue, wouldn't this be bad for user experience? Should't we consider another approach?

Do you have another approach in mind @sanjin-saric?

It may be possible to do faster data-driven paint property changes if we switch our buffers from containing presentational data to containing feature property data. (This is implicitly being considered in https://github.com/mapbox/mapbox-gl-style-spec/issues/47). This is will be a _big_ project.

If I were looking to implement this functionality, I would use the approach outlined in https://github.com/mapbox/mapbox-gl-js/issues/3170#issuecomment-270465042 and then invest some energy in optimizing the buffer creation codepth.

@lucaswoj
I've been digging around this:

populatePaintArray(layer, paintArray, length, globalProperties, featureProperties) {
        const start = paintArray.length;
        paintArray.resize(length);
        for (const attribute of this.attributes) {
            const value = getPaintAttributeValue(attribute, layer, globalProperties, featureProperties);

            for (let i = start; i < length; i++) {
                const vertex = paintArray.get(i);
                if (attribute.components === 4) {
                    for (let c = 0; c < 4; c++) {
                        vertex[attribute.name + c] = value[c] * attribute.multiplier;
                    }
                } else {
                    vertex[attribute.name] = value * attribute.multiplier;
                }
            }
        }
    }

Figured out this is where the magic happens.

I have a feeling that the "buffer containing feature data" could solve our problems.

Lets take a common situation. Lets say we have data-driven map like this one:

alt text

And we want smooth transitions to say some blue shade. The key thing is that the map data stays the same. This fact we can use. Since the features don't change, there is no logical reason why the order of colors in paintArray shouldn't be the same.

I am thinking that if we store the info how we added color to this paintArray, we might be able to make transitions between one color stop definition to another.

Maybe I am misunderstanding the code, correct my logic if I'm wrong.

Your understanding of the code is correct!

I am thinking that if we store the info how we added color to this paintArray, we might be able to make transitions between one color stop definition to another.

Doing this elegantly and performantly is the crux of the problem. I encourage you to take a swing at it.

Adding additional 馃憤 to this ticket with the JSON client data-join example now live. Users exploiting DDS for data-joins for data visualization will want smooth transitions to show change over time (or other dimensions).

cc @kronick

I started doing this task. I will have to make a PR here as well as mapbox-gl-style-spec repository. I am experimenting with the categorical function for now, it will have to return both color and the value of the stop. Currently, I am trying to find a way to store stop value in buffers.

@sanjin-saric did you make any progress on this DDS-transition feature? Please link to your PR if so.

Hey, so two years later transitions still don't work on data-driven properties?

@mayteio hey, if you think this is so easy to implement, please welcome to do so and submit a PR.

Did anybody consider merging mapbox-animate back into the core? The animation performance is superior!

In the absence of a fix here, some documentation would be great - spent a long time trying to debug why my DDS weren't transitioning.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

BernhardRode picture BernhardRode  路  3Comments

Scarysize picture Scarysize  路  3Comments

stevage picture stevage  路  3Comments

jfirebaugh picture jfirebaugh  路  3Comments

aaronlidman picture aaronlidman  路  3Comments