mapbox / mapbox-gl-js

Interactive, thoroughly customizable maps in the browser, powered by vector tiles and WebGL
https://docs.mapbox.com/mapbox-gl-js/
Other
11.2k stars 2.22k forks source link

Add a per-layer opacity property #4090

Open lucaswoj opened 7 years ago

lucaswoj commented 7 years ago

From @nickidlugash on March 25, 2015 20:54

Background: https://github.com/mapbox/mapbox-gl-js/issues/859#issuecomment-65845587

Is this currently possible for JS/native to render (or will it ever be)?

Useful for layers that are designed to have overlapping geometries, such as all the layers in Mapbox Terrain.

Copied from original issue: mapbox/mapbox-gl-style-spec#273

lucaswoj commented 7 years ago

From @nickidlugash on March 31, 2015 21:34

It looks like the current opacity properties have switched to per-geometry. So I guess the new question is: can we add a per-layer opacity property? Useful for tunnels on basemaps:

screen shot 2015-03-31 at 5 33 36 pm

@samanpwbb @ajashton Any thoughts?

@ansis @kkaefer is this feasible?

lucaswoj commented 7 years ago

From @samanpwbb on March 31, 2015 21:37

What if setting RGBA fill/stroke was per-feature while setting Opacity was per layer?

Both per-feature and per-layer are important, but if I had to pick one I'd pick per-layer (to avoid the kinds of problems you can see in the screenshot above).

lucaswoj commented 7 years ago

From @nickidlugash on April 1, 2015 18:21

What if setting RGBA fill/stroke was per-feature while setting Opacity was per layer?

This seems like a good idea for me. I don't currently tend to use a lot of RGBA values, but this might make more sense than implementing two different opacity properties for each layer type.

lucaswoj commented 7 years ago

From @kkaefer on April 2, 2015 9:43

Per-layer and per-feature alpha values are hard to implement; a per-layer alpha value means that we'd have to render to a buffer first, then composite onto the main framebuffer.

lucaswoj commented 7 years ago

From @nickidlugash on May 1, 2015 19:2

Per-layer and per-feature alpha values are hard to implement; a per-layer alpha value means that we'd have to render to a buffer first, then composite onto the main framebuffer.

@kkaefer does this mean that having a per-layer opacity property would take a lot of time/energy but is doable, or that it's something you don't think we should consider doing at all?

lucaswoj commented 7 years ago

From @ansis on May 1, 2015 19:7

We could implement per-layer alpha by just using the depth buffer to prevent double drawing. We would have to draw lines with two calls so that we can draw the solid part first and the antialiasing second. It wouldn't be exactly the same as carto if you have both per-layer and feature-level opacity, but this case doesn't seem that important.

lucaswoj commented 7 years ago

From @jfirebaugh on June 28, 2016 0:0

Can someone define what "per-layer" opacity means precisely? Or with an example? E.g. if you have a layer with a red triangle at 50% opacity on top of a blue square at 50% opacity, with a "layer opacity" of 50%, how is that supposed to render?

lucaswoj commented 7 years ago

From @nickidlugash on June 28, 2016 15:27

@jfirebaugh I think like this (although I'm not sure I'm rendering @ansis's suggestion correctly):

screen shot 2016-06-28 at 11 25 49 am

/cc @samanpwbb

lucaswoj commented 7 years ago

From @samanpwbb on June 28, 2016 15:33

Yep, what @nickidlugash said. I would expect the cartoCSS behavior rather than Ansis's suggested implementation in cases where there is both per-layer and per-feature opacity. Here's an example with strokes that illustrates how per-layer opacity might be preferable:

screen shot 2016-06-28 at 11 32 59 am

lucaswoj commented 7 years ago

From @jfirebaugh on June 28, 2016 16:12

Thank you, those examples are great.

I believe the annotations here are correct:

image

The cartoCSS behavior is the one that requires composited rendering (rendering the layer first to a buffer, then compositing that layer with the scene using the layer-wide opacity).

lucaswoj commented 7 years ago

From @ajashton on June 28, 2016 16:26

Normally it's not really necessary to have both per-object and per-layer opacity on the same layer, just one or the other. So if we can't fully replicate the Mapnik behavior then that's fine, just these two are key:

screenshot-2016-06-28-12 23 15

lucaswoj commented 7 years ago

From @jfirebaugh on June 28, 2016 16:30

With data-driven styling it's already possible to set a different fill-color rgba value for each feature. So it's pretty awkward to prohibit per-feature opacity.

lucaswoj commented 7 years ago

From @ezheidtmann on September 3, 2016 22:30

It looks like this is now implemented for fill layers via the fill-opacity paint property. Is there any way to do this for line layers? The line-opacity property seems to set a per-geometry opacity, at least in js v0.23.0.

jaapster commented 6 years ago

It would help us a lot if this feature was implemented. Is there any traction on this issue?

cyrilchapon commented 6 years ago

Up ! I dare to give a textual šŸ‘ to it, as we deadly need that.

It looks like this is now implemented for fill layers via the fill-opacity paint property

Actualy the visual behavior is more a feature-opacity

EDIT: clarification on our use case. We're displaying some "zones" (polygons) which represent, say danger zones. They are displayed in red, they are polygons overlays. We don't want to display the information about "cumulative danger", we just want to display in a simple motion the "total zone" represented by the union of every Features. Currently, mapbox.gl does not offer a way to accomplish that in a semi-transparent layer. (our current solution is to pre-process every single layer, and to turf.union them... which is not very efficient)

mirkoclemente commented 6 years ago

I would really appreciate this feature. I need to overlay a historical map with transparent roads. I putĀ the raster layer above the road layer and set raster-opacity to a value below 1. Unfortunately, this workaround affects theĀ mapĀ appearance and makes it looking colorless.Ā 

davidswinegar commented 6 years ago

I also need this feature. I need to overlay a group of roads with a transparent layer, and with the currently available transparency options, any intersections of roads lead to a darker patch.

Plantain commented 6 years ago

It seems like this and several other open feature requests would be solved by bringing back compositing - I understand the reasons it was dropped in https://github.com/mapbox/mapbox-gl-js/issues/523 , but that was a long time ago and hardware performance is much higher than 4 years ago. Can this be revisited?

stevage commented 5 years ago

Just a belated vote for this as well. My usual use case is boundary layers rendered as line features. I basically can't use opacity at all because it looks like this:

Screenshot 2019-03-19 17 30 00

All the places where two boundaries are contiguous creates a double-weight line, compared to the edges of the boundaried area.

Notice we also get these unpleasant extra-heavy bits at every sharp bend in any line feature. Presumably per-layer opacity would solve that too.

robhawkes commented 5 years ago

Another vote. Hit this today when we needed to reduce the opacity of some overlapping features on a layer without the overlapping areas looking darker.

andrewharvey commented 5 years ago

@stevage I know this doesn't completely solve this ticket, but taking the mesh of those polygons can help eliminate one source of the double-weighted lines.

https://github.com/andrewharvey/geojson-mesh or https://github.com/mapbox/tippecanoe/issues/575

cyrilchapon commented 5 years ago

This issue need attention from mapbox contributors back..

stevage commented 5 years ago

@andrewharvey Thanks for the pointer! Just for clarity, does "extract shared borders" really mean "generate a non-overlapping set of borders"? (Ie, it doesn't just include the overlapping parts, right?)

agrignard commented 5 years ago

I am adding a +1 for this feature, I am trying to apply a global transparency to a layer of type circle but it doesn't work. Of course I can also set an alpha to my color but it would be great to be able to control it only with one line.

saneth commented 5 years ago

This feature would help us immensely as well. We have layers with overlapping features but the desired visualization is not to add the feature opacities.

kaligrafy commented 5 years ago

+1: Using union on thousands of polygons is a performance killer! And when some polygons have holes, it cause display issues.

georgbachmann commented 5 years ago

+1 from me as well. My lower-opacity tracks on my map look strange where they connect.

Bildschirmfoto 2019-08-26 um 08 27 57
ccspglobal commented 4 years ago

still no resolution for no aggregate opacity for overlapping circles on same layer??

supersteves commented 4 years ago

+1. It's impossible to do nice-looking translucent country borders without costly preprocessing of the data beforehand, the overlapping borders appear more intense than the outer borders.

I suggest a layer opacity option which, if configured (with warnings) enables buffer based compositing.

florianPOLARSTEPS commented 4 years ago

Same here. We would love to see a possibility to control opacity per layer since it would give us a lot of flexibility with our animations. We would love to show and hide symbol layers with a fade transition but using the icon-opacity property for every single symbol seems like a hack and collides with the overlap- algorithm used by mapbox which also targets the icon-opacity when doing the fade in/out.

jasonhibbs commented 4 years ago

Per-layer, and per-group

dyakovlev commented 4 years ago

Posting to bump this back up. Currently running into a lot of semi-transparent self-overlap issues with a line layer used to show a buffer around another line layer.

Screen Shot 2020-03-18 at 12 01 14 PM

Interestingly, when zoomed out, the self-overlaps stack so much that the layer becomes opaque.

Screen Shot 2020-03-18 at 12 05 37 PM

Maybe this is a separate issue with line-join rendering?

xwipeoutx commented 4 years ago

Throwing my +1 behind this as well. You have enough sample pictures though, mine i much the same :)

brianjacobs-natgeo commented 4 years ago

+1 as well. This is especially apparent to me when trying to blend line features atop varying and richly colored rasters

image
waissbluth commented 4 years ago

+1

tomtaylor commented 4 years ago

This would be brilliant to add. My use case is highlighting certain roads which are better for cycling, using a semi-transparent line. The overlaps and line joins cause a lot of visual issues as it stands.

MajorClod commented 4 years ago

This would be incredibly useful. My use case is to toggle on/off different layers or groups inside a Mapbox Style, basically enabling a graceful fade out of layers when the user does this. Currently I need to have a rather elaborate stack of code that a)

It would be much easier if we had something like:

map.setLayoutProperty(layerId, 'opacity', 0.5);

Desired outcome is basically to take all the individual feature opacities and multiply them by the "Layer" opacity.

acarnagey commented 4 years ago

Preventing increased opacity on overlapping / stacked polygons with mapbox would be great, I like mapbox but it is preventing me from switching from google maps because I can't do this sort of thing in mapbox.

Screen Shot 2020-08-04 at 8 02 19 PM
anderswi commented 4 years ago

+1, I'm also trying to use transparent lines, which is blocked by the self-overlapping problem.

coreyrowell commented 3 years ago

+1, I pull in land ownership tiles to overlay. In most cases the bounds overlap on sides and corners. In the case of overlapping corners it darkens to the point of hiding the underlying map layer. Screenshot from 2021-04-02 01-13-29

karimnaaji commented 3 years ago

A proof of concept fixing the issue of overlapping geometry is proposed in https://github.com/mapbox/mapbox-gl-js/pull/11082. The biggest tradeoff is around aliasing (refer the screenshots from the PoC), if anyone has styles they could share for this issue it'd be great to have more cases to test against.

ezheidtmann commented 3 years ago

@karimnaaji Looks great! I'm not working with that type of geometry at the moment, but the demo data you have is identical to our use case -- essentially taking every piece of OSM street geometry and rendering each as a separate line feature. We used round caps, and chose one of three colors for each feature.

zhangyiatmicrosoft commented 2 years ago

I think I found a solution for polygons (NOT lines). The answer is to use "fill-extrusion" (3d), not flat polygons -- it makes sense because we want polygons at higher elevations to cover others, not blend.

Full example here: https://jsfiddle.net/zyatmsft/zp2cy5dk/21

Three critical points: 1) The rings much close. Ordinary "fill" layer is tolerant, but not "fill-extrusion" 2) Give each polygon an arbitrary "elevation" (or z-index ...whatever you like to call it). Looks like the gap needs to be > 100 (meters), otherwise they start to overlap. 3) set 'fill-extrusion-height' and "fill-extrusion-base" based on the value from (2) above. This is needed especially when the map is tilted.

Amber-372 commented 2 years ago

+1

charlesxbai commented 2 years ago

+1, I'm drawing multiple circles on the same layer, and if I try to fill them, the dense areas will become completely solid, is it possible for us to implement it for circle as well?

jaapster commented 2 years ago

It would be great if this issue/feature would be given some attention by Mapbox. There is enough demand for it. The issue is more than 5 years old now ...

zhangyiatmicrosoft commented 2 years ago

+1, I'm drawing multiple circles on the same layer, and if I try to fill them, the dense areas will become completely solid, is it possible for us to implement it for circle as well?

See my workaround for polygons, posted at 2/28. Circles could be simulated with polygons with many edges. Not a perfect solution, I know but at least it will get things going.