Open ianthetechie opened 3 years ago
That looks like an oriented buffer around the A3 text label. But the other road labels don't have that issue. I don't remember seeing a bug like this while at Mapzen working on Tangram-based styles, you might have found something novel! :)
I took a look at the yaml that was generated and noticed this:
highway_name_major:
data: {layer: transportation_name, source: openmaptiles}
draw:
text:
blend_order: 37
buffer: 350px
font: {family: Open Sans Regular, fill: '#ccc', priority: 962, size: 13, transform: uppercase}
move_into_tile: false
style: overlay_text
In the source .json you have this:
"layout": {
"symbol-avoid-edges": true,
"symbol-placement": "line",
"symbol-spacing": 350,
I suspect you're trying to avoid label repetition -- if so, you'll want to use repeat_distance
instead of a buffer.
https://tangrams.readthedocs.io/en/latest/Syntax-Reference/draw/#repeat_distance
Good eye @burritojustice! Yes, buffer: 350px
will ensure there is at least 350px of space around each label, hence that one lonely A3 in the middle 🤣
repeat_distance
is indeed useful for preventing the same label text from repeating too closely. It doesn't affect where the labels are placed though, just if they are shown or hidden (the default value is usually fine too though).
For label placement along a line, the parameters you want that correspond to MBGL are documented here: https://tangrams.readthedocs.io/en/master/Syntax-Reference/draw/#placement
So I believe the equivalent would be:
draw:
text:
placement: spaced
placement_spacing: 350px
...
There are also some more esoteric options like https://tangrams.readthedocs.io/en/master/Syntax-Reference/draw/#placement_min_length_ratio.
Some examples from Mapzen basemaps (with zoom stops on some of those params): https://github.com/tangrams/bubble-wrap/blob/ab18c141a1f782f113c449e2df86ed966598eb75/bubble-wrap-style.yaml#L1601-L1602 https://github.com/tangrams/bubble-wrap/blob/ab18c141a1f782f113c449e2df86ed966598eb75/bubble-wrap-style.yaml#L1556-L1567
Wow, thanks a lot guys for taking the time to look through these! Yes, you're right. That was totally an implementation error on my end. Using placement: spaced
and placement_spacing: 350px
does the trick.
I may circle back next week if I'm unable to roughly match the label precedence, but I did find docs on that so I'll check those first.
Cheers!
I think I've fixed most of the issues I had with priority/precedence of text labels (I accidentally attached the priority
to the font
block instead of text
). However, there's something a bit amiss still. The following sequence illustrates how labels that are supposed to be a lower (higher numerically in Tangram) priority can crowd out ones that are supposed to be more important. It looks like the highway_name_motorway
labels can sometimes crowd out place_city_large
(screenshots show the difference between 2 scroll wheel clicks of zoom).
I've included the two layers below. Maybe someone can spot what I missed.
highway_name_motorway:
data:
layer: transportation_name
source: openmaptiles
draw:
text:
blend_order: 38
font:
family: Open Sans Regular, Noto Sans Arabic Regular, Noto Sans Ethiopic
Regular, Noto Sans Thai Regular, Noto Sans Khmer Regular, Noto Sans Lao
Regular, Noto Sans Myanmar Regular, Noto Sans Tamil Regular, Noto Sans
Bengali Regular, Noto Sans Devanagari Regular, Noto Sans Hebrew Regular,
Noto Sans Armenian Regular, Noto Sans Georgian Regular, Noto Sans JP Regular,
Noto Sans SC Regular, Noto Sans TC Regular, SeoulNamsan M, Noto Sans Regular
fill: hsl(214, 11%, 65%)
size: 14
stroke:
color: hsl(0, 0%, 20%)
width: 2.0px
move_into_tile: false
placement: spaced
placement_spacing: 350px
priority: 961
style: overlay_text
text_source: ref
filter:
all:
- $geometry: line
- class: motorway
place_city_large:
data:
layer: place
source: openmaptiles
draw:
icons:
blend_order: 44
order: 44
size: 40.0%
sprite: circle-alt-11
text:
anchor: right
blend_order: 44
font:
family: Open Sans Regular, Noto Sans Arabic Regular, Noto Sans Ethiopic
Regular, Noto Sans Thai Regular, Noto Sans Khmer Regular, Noto Sans
Lao Regular, Noto Sans Myanmar Regular, Noto Sans Tamil Regular, Noto
Sans Bengali Regular, Noto Sans Devanagari Regular, Noto Sans Hebrew
Regular, Noto Sans Armenian Regular, Noto Sans Georgian Regular, Noto
Sans JP Regular, Noto Sans SC Regular, Noto Sans TC Regular, SeoulNamsan
M, Noto Sans Regular
fill: '#9aa2ac'
size:
- - 4
- '11'
- - 12
- '18'
- - 14
- '22'
stroke:
color: hsl(0, 0%, 20%)
width: 2.0px
transform: uppercase
move_into_tile: false
priority: 955
style: overlay_text
text_source: 'function() { return `${feature["name:latin"] || ''''}
${feature["name:nonlatin"] || ''''}`.trim() }'
filter:
all:
- $geometry: point
- all:
- not:
capital: 2
- rank:
max: 4
- class: city
What happens when you remove the blend_order
bits?
What does style: overlay_text
reference, is there a link to the full scene file?
An aside: That's an insane number of font family fallbacks! Does OpenSans not provide those codepoints by default?
Without blend_order
, the ordering ends up wrong and the text is (partially) buried. My understanding is that blend_order
is necessary when drawing with transparency. In Mapbox there is no such use of Photoshop style blend modes, but it looks like these are necessary in order to draw any colors with alpha (which our styles use heavily at the moment).
overlay_text
is one of the "magic" blend combination styles that Tangram creates for you. It's a text style that sets the blend mode to overlay
. I suppose I could change this to blend: overlay
but both appear to have the same effect.
Here's a scene file; looks like GitHub won't accept yaml so I zipped it. scene.yaml.zip
Finally, here's the back story on the fonts ;) Open Sans does actually include these glyphs (if you get the massive version of it at least). We used the lighter version of Open Sans for most glyphs. Then we tracked down what we thought were better looking fonts for less common scripts. For example, the Korean Government has a font that looks pretty great and is really familiar to anyone in Korea so we use that for Korean glyphs to improve the typography. One unsolved mystery to me is that the glyphs actually render (for Korean, for example) even if I only specify Open Sans as the font, but Tangram (correctly?) picks the SeoulNamsan M
glyph when rendering Korean text. So either it is automatically falling back to system fonts like Helvetica for these glyphs or I misunderstand how it works. At any rate, the fonts are indeed being selected according to the correct order and match what I expect in all languages that I can read / care about the typography at least ;)
Also note that Mabox's font rendering is a bit different... the TL;DR is that you have a "font stack" and the order here gets converted into a request for glyph ranges (of 256 glyphs each). The server then returns the glyphs in the range you requested with the font precedence you requested as a protobuf packed SDF (signed distance field) glyph package which is then rendered by Mapbox GL (JS). It doesn't use any actual "font" technologies at all; it's a rather different way of rendering fonts so you can get away with specifying a bunch of weird fonts like this and it doesn't affect performance. I'll of course consider making a custom "superfont" instead to save renderer work, but hopefully this bit of trivia was interesting ;)
Update: Yeah, the (normal at least) Open Sans definitely doesn't have CJK glyphs. Since Tangram seems to leverage browser font rendering at some level, it must have been falling back to Helvetica before I added the other fonts. That's why we have Noto etc. because that fills out the rest of the languages. This is likely then less necessary in Tangram as it can fall back to browser defaults or whatever, but I think adding them is helpful since it makes the rendering more consistent / explicit and many machines don't have fonts with CJK glyphs out of the box.
Also, for the scene file I attached you'll notice I have 2 fonts hardcoded for now. The rest will be fleshed out in #3.
It looks like the blend_order
is changing for each "label" layer, but I think you generally want them to be in the same "render pass" instead?
BTW, in the draw blocks you should be able to just say the style name directly instead of setting it later? So draw: { inlay_lines: ... }
and then you wouldn't need to restate some of the other properties, too?
Nice, that makes sense about how you're setting up the fonts. Since the font family set is always the same, you can make it into a globals
variable and then reference it each time instead of repeating the list?
Nit: Consider moving the filter
section above the draw
section so it's easier to reason about what is being shown before how it should be shown? Either work, but if you're reading a bunch of scene file's it'll make it easier?
Hmm, good point. I will try to simplify that blend_order
. You're right; all labels should end up at the top and priority
should take care of precedence alone. I'll simplify that by setting them all to a massive value. That doesn't seem to change the result, but makes logical sense.
Good call on just moving the style up a level rather than wasting an extra key. I forgot about that feature (even though I used it elsewhere...).
Good suggestion on moving the filter
higher. pyyaml
appears to sort keys by default, but I think I can override this.
This may be a core Tangram issue, but currently generated styles seem to have huge areas where labels are initially rendered but then disappear, presumably due to Tangram's label placement or collision constraints. Additionally, the precedence/priority does not seem to be quite right. This is probably an implementation error on my part.
Here is the source GL JSON style that exhibits the issue: https://tiles.stadiamaps.com/styles/alidade_smooth_dark.json (you can run a server on
localhost
to test; see https://docs.stadiamaps.com/ for auth info). Below is an example of such a "hole" at a particular zoom level in Germany.