-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
RFC: Stretchable icons #8917
Comments
With this proposal, the only way to resize icons is |
This looks great – excited to get this in gl and eventually add support in Studio. I have some specific questions about the SVG format:
My hunch is that we may want to be strict rather than loose with enforcing constraints on the format. Likely if a keyword element is inside a transform, for example, the user just did something wrong and would benefit from a helpful error message but I can see arguments for both loose and strict enforcement. We can hash some of these questions out in mapbox/spritezero#68 if we aren't sure, – then we should definitely document the SVG spec in detail when it's finalized. |
camel case
I think this should be maybe a flat array?Most commonly there will only be one stretch zone. It would be nice to avoid the nesting in that case maybe content vs paddingThe Also, what would the behavior of
If the text is 40px would the icon be 82px wide? |
Prior art:
|
I agree with @ansis' points above on naming:
|
I discussed some of these points with @ansis and @kkaefer last week but didn't post a ticket update: camel caseWe agreed to camel case for the sprite.json and GL-JS API to match existing precedent there, but keep
in the svg metadata for greater clarity. flat vs nested arrayThe relationship between each stretch zone is clearer with a nested array. With 2 (or more) stretch zones, It's harder to check your work and to keep your numbers straight. Also, the benefit of removing one set of brackets is minor. content vs paddingWith A secondary benefit: Finally, I understand that
When your stretchable icon is a rectangle, you might be indifferent between thinking about this in terms of Finally, I think the name
I'm not sure that we know this will be true for users of this feature. A background box design where the top padding or the bottom padding is larger than the other could be the more common for users of this feature. My point is I wouldn't overindex on this specific use case of symmetrical padding.
I'm not sure if these enhancements would provide a net benefit or if they would just create greater confusion. More ways to do the same thing are not always better. |
merged with the originally proposed parameters in #8997 |
We intend to implement stretchable icons, aka 9-part icons. Mapbox GL currently supports
icon-size
, which linearly resizes the entire icon in both dimensions. Stretchable icons allow defining certain areas of an icon that may be stretched, leaving the remaining areas of an icon at a fixed size. This is useful for icons that need to accomodate text of varying width, e.g. highway shields, or text frames.This is how we imagine our implementation will look like:
Sprite JSON format
The metadata file that describes a sprite image already contains information about where an image is within a sprite, as well as the pixel ratio. We're going to add three fields:
content
: An array of 4 numbers, which represent two coordinates relative to the top left of the icon that span up a rectangle. Both coordinates must be within the dimensions of the icon, and the second coordinate must be greater than the first coordinate. The rect must have have a positive area. When sizing icons withicon-text-fit
, the icon size will be adjusted so that the this content box fits exactly around the text. If one axis of the icon is not stretchable, the center of the content box will be aligned with the center of the text. Anyicon-text-fit-padding
values will be applied around the text, and the icon size will be adjusted appropriately.Example:
"content": [ 2, 4, 16, 9 ]
stretch-x
/stretch-y
: An array of 2-element arrays that specify between which coordinates the icon may be stretched. Consequently, an image may have more than one stretch area, e.g. to allow for a central embellishment that should remain at fixed width. Stretch areas are specified independently for both axes, and either axis may not have any stretch areas at all, meaning that it should only be stretched one one axis. The 2-element arrays specify absolute distances in pixels to the top left corner. Stretch areas may not overlap and they must be ordered ascendingly.Example:
"stretch-x": [[ 2, 8 ]]
Icon Rendering
Existing, non-stretchable icons are rendered with a quad (i.e. two triangles) that transfers (and scales) the texture from the image atlas. For stretchable icons, we still copy the icon as is into the image atlas, but instead use multiple quads to render the icons. The quads copy the appropriate portion of the icon from the image atlas, either in a true-to-pixels way, or stretched, based on the metadata found in the Sprite JSON.
This implementation strategy means that a stretchable icon in different sizes will not occupy more texture space, but it will occupy some vertex space. While the implementation will support an arbitrary number of stretch zones, we expect most icons will be limited to one or two stretch zones per axis.
Runtime API
We support runtime APIs to add images. They already support supplying metadata, like the
pixelRatio
, and will now also accept metadata for stretchable icons.Icon Authoring
Icon designers will be able to add paths or shapes without and specific IDs (= layer names in Ilustrator and Affinity Designer):
The Mapbox API will parse SVGs and extract the metadata. Multiple stretch zones can be defined by using multiple paths who’s id property begins with
mapbox-icon-stretch-x
(ormapbox-icon-stretch-y
). Alternatively, user can define a single rectangle with the IDmapbox-icon-stretch
to define the stretch zones for both axes simultaneously. The content area can be defined with a rect ofmapbox-icon-content
. All of these objects can be objects of any shape or path, but their bounding rectangle will be used for metadata generation./cc @mapbox/gl-js @mapbox/gl-native @mapbox/studio @mapbox/map-design-team
The text was updated successfully, but these errors were encountered: