Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interpolating text-size and exponentially scaling by zoom level with expressions #7563

Closed
sdawson26 opened this issue Nov 7, 2018 · 3 comments

Comments

@sdawson26
Copy link

sdawson26 commented Nov 7, 2018

Motivation

Our map renders layers that were created in CAD software. Every tile source contains its own custom set of labels with a "font-size" property. For example, a simple property looks like this:

{ "label": "Map Label", "font-size": 72 }

What we need to do is allow users to increase the map's text size as high as 200% or decrease it as low as 50%. The problem is that we cannot achieve the desired outcome with expressions.

To re-create the problem, let's say we already have an outside operation that calculates how the font size should scale exponentially from zoom 5 to zoom 25 that gets defined to the property's 'font-size-min' and 'font-size-max', respectively:

  map.setLayoutProperty('points','text-size',[
    'interpolate',
    ['exponential', 2],
    ['zoom'],
    5, ['get','font-size-min'], // let's assume this == 18
    25, ['get','font-size-max'] // let's assume this == 300 (exceeds the 255 limit)
  ]);

The code above should behave similar to just hard-coding these values:

  map.setLayoutProperty('points','text-size',[
    'interpolate',
    ['exponential', 2],
    ['zoom'],
    5, 18,
    25, 300
  ]);

See a JSFiddle example

When using the JSFiddle example, clicking "Without expression" increases the font size as expected (even beyond the 255 maximum). However, when you click the "With expression" button, the font size reverts back to a default text size (24) and we get this error in the console:
points: Value for "text-size" is >= 256. Reduce your "text-size".

Our attempt to get around this is to use the "min" expression like so:

 map.setLayoutProperty('points','text-size',[
    'interpolate',
    ['exponential', 2],
    ['zoom'],
    5, ['min', ['get','font-size-min'], 255], 
    25, ['min', ['get','font-size-max'], 255]
  ]);

The problem with "min" is that we lose the desired rate that the text scales based on the zoom level. We're ok with enforcing a maximum value of 255 if that's what it takes, but we don't want to change the rate of scale that we see when "min" isn't used.

Potential solution

I see one of three ways this could be resolved:

  1. Don't enforce a text-size maximum at all (this might have performance consequences).
  2. When the expression exceeds the maximum value, fallback to the maximum of 255 rather than the default value of 24.
  3. Somehow let "min" not affect the overall rate of change at which the text-size scales.

Please let me know if you need me to clarify anything. Thanks!

@sdawson26 sdawson26 changed the title Interpolating text-size and exponentially scaling with expressions Interpolating text-size and exponentially scaling by zoom level with expressions Nov 7, 2018
@asheemmamoowala
Copy link
Contributor

Duplicate of #7163

#7125 introduced a warning when text-size has a value that is too large.

@Emixam23
Copy link

Hey guys, I know this issue is closed for a while now but how would I be able to do the same with Marker components?

@arthur-clifford
Copy link

I don't know if this is what anybody is lookng for, but If you use a marker controllable by a css class you can track changes to map zoom level and add/remove zoom level classes zoom-1,zoom-2,etc to the div for your map component then:
In your css you could define things based on zoom level and your
.zoom-1 .my-class { width:12px; height:23px;; }
.zoom-10.my-class {width:23px; height:34px;; }

You can also add classes to the map div like zoom-above-10 or zoom-below-3 etc and alter styles settings as appropriate.

You could also have different sets of sizes for instance sm, med, and lg (to borrow from bootstrap) so that you could do:
.zoom-above-10 .pt-sm { width: 2px; height: 3px; }
.zoom-above-10 .pt-md { width: 3px; height: 4px; }
.zoom-above-10 .pt-lg { width: 5px; height: 6px; }

So, for your marker's dom-element if it had the class 'pt-lg' and the map programmatically had the class 'zoom-above-10' then scaling the map above or below 10 will apply the right style without having to call any functions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants