tangrams / tangram

WebGL map rendering engine for creative cartography
https://tangram.city
MIT License
2.22k stars 290 forks source link

Add support for text highlight boxes #724

Closed nvkelso closed 4 years ago

nvkelso commented 5 years ago

Similar to https://github.com/tangrams/tangram/issues/723 which proposes text underlines, I'd like to a new text treatment to callout country and regional capitals in map styles. We adding better support for both in the new v1.8 Tilezen schema, but right now the only way to call them out visually is to change the color. Another common technique in cartography (especially in Europe) is to "highlight" the text with a yellow or orange box shape behind the text.

There are two options for the shape – if there is letter spacing (or spaces) the highlight should optionally continue as one shape... but the default is usually to only do it behind word blocks.

bdon commented 4 years ago

A cheap way to do this may be to draw a rectangle behind the text when it's being rasterized on canvas. This would depend on getting the metrics right with letter-spacing etc applied so the border around the text is consistent. It would also mean the background cannot have an alpha independent of the text, but that seems like an acceptable compromise.

Example screen:

Screen Shot 2020-06-08 at 3 00 10 PM
bcamper commented 4 years ago

Funny, I was looking at exactly this last night too (re-familiarizing myself with the text rendering code thinking about vertical CJK text, and remembered this issue).

I agree the Canvas background box approach is a good tradeoff for this (and we use a similar approach for texture/collision box debug rendering already). It's not the most optimized (would increase the label atlas size for different color background boxes that otherwise share the same label text + font), but that is unlikely to happen frequently and it's a low code footprint to implement. It is less straightforward for curved labels though, due to order issues with the background boxes overlapping nearby segments, so limiting it to point labels -- which I believe is the main use case -- would also make for an easier initial implementation.

I've pushed my work on this here: https://github.com/tangrams/tangram/compare/text-box

tangram-1591579291300

Note that while it does apply the recently added alpha parameter in the font block (#740) to both the fill and background when it is present, it is also possible to set a different alpha for the two directly, e.g.:

font:
  fill: [1, 1, 1, 0.75] # white text w/75% opacity
  background: [1, 0.5, 0, 0.5] # orange background w/50% opacity
  ...

@nvkelso how does this look to you?

bdon commented 4 years ago

This is a much better implementation than mine :)

https://github.com/bdon/tangram/commit/570f9c3fdae3bf38fba209f09728a12cc33accc7

I was thinking maybe even:

font:
   fill: [1, 1, 1, 0.75] # white text w/75% opacity
   background: 
      fill: [1, 0.5, 0, 0.5]
      stroke: black
      strokeWidth: 2px

which would call strokeRect in the rasterization code. it may act funny with strokeWidths more than a couple px though? worth experimenting.

nvkelso commented 4 years ago

💯 Loving this! Most often I see this in print maps as solid background, but I do see it sometimes with a stroke as well so like @bdon's proposal.

(If more than one background is used sometimes the color is varied, but if it's to emphasize a slight information difference then the graphic stroke is applied.)

bdon commented 4 years ago

https://github.com/tangrams/tangram/compare/text-box#diff-696dc4f88f682e93455a7a17a688f0bcR52

This excludes "points" draw styles applied to line geometries. A use case may be very basic sprite-free highway shields like I posted above, so I think it should be changed.

bcamper commented 4 years ago

This excludes "points" draw styles applied to line geometries. A use case may be very basic sprite-free highway shields like I posted above, so I think it should be changed.

Oh, yep that was an oversight, I agree this should apply to any point label, regardless of underlying geometry.

bcamper commented 4 years ago

Just a quick note here to say I haven't forgotten this :)

Ran into some apparent issues with collision detection that need to be addressed. The addition of border stroke also adds potential complexity there... all the result of pushing this to be more of a "real" feature vs. a quick hack. Not a bad thing though, just takes a bit more time. Have been busy elsewhere but hoping to look at it soon.

bcamper commented 4 years ago

Fixed collision issues for background box in the branch: https://github.com/tangrams/tangram/compare/text-box

I'll see if adding the stroke is straightforward, and if not, maybe we start with just the background (or with a stroke of fixed width).

bcamper commented 4 years ago

released in v0.21.0