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

Add vertical-align in format expression #900

Open
wants to merge 15 commits into
base: main
Choose a base branch
from

Conversation

stanislawpuda-tomtom
Copy link

@stanislawpuda-tomtom stanislawpuda-tomtom commented Nov 13, 2024

Related issue #832.

This PR introduces vertical align property to format expression. It enables to specify how each section should be positioned in relation to biggest element in line. There are three possible options:

  • "bottom" default: text baseline or image bottom are in line - this is current behaviour.
  • "center": image center or text center are in line.
  • "top": image top and text top are in line

Launch Checklist

  • Confirm your changes do not include backports from Mapbox projects (unless with compliant license) - if you are not sure about this, please ask!
  • Briefly describe the changes in this PR.
  • Link to related issues.
  • Include before/after visuals or gifs if this PR includes visual changes.
  • Write tests for all new functionality.
  • Document any changes to public APIs.
  • Post benchmark scores.
  • Add an entry to CHANGELOG.md under the ## main section.

@codecov-commenter
Copy link

codecov-commenter commented Nov 13, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 92.80%. Comparing base (c6fd205) to head (37e1178).
Report is 11 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #900      +/-   ##
==========================================
+ Coverage   92.78%   92.80%   +0.01%     
==========================================
  Files         107      107              
  Lines        4739     4752      +13     
  Branches     1346     1352       +6     
==========================================
+ Hits         4397     4410      +13     
  Misses        342      342              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@stanislawpuda-tomtom
Copy link
Author

I would like to cover questions from the meeting on Nov 13th:

Using HTML

I did check, and it is possible to use HTML to display vertically aligned labels. This approach works for MapLibre GL JS, however it does not cover multiple platforms. There are more advantages of using format expression over custom HTML layer:

  • much easier to use
  • HTML markers don't support collision detection, as far as I know, which makes the implementation even more difficult
  • better performance
  • defined once in the style spec for multiple platforms

Format expression already gives possibility to create rich labels on the map, easily, without having to implement own custom solution. Having the possibility to align elements vertically in my opinion is good supplement to format expression. In some cases necessary to make full benefit from it.

Sample use case

Our team created a sample mock how the labels look like with and without vertical alignment.

Before:
before

After:
after

@lseelenbinder
Copy link
Member

Thanks for taking the time to work through these pieces @stanislawpuda-tomtom!

In my opinion, those advantages are sufficient to merit including in the spec—especially for collision detection and performance reasons.

@stanislawpuda-tomtom
Copy link
Author

I have changed baseline to bottom.
I also modified one test to check if vertical-align is recognised for image section.

@HarelM
Copy link
Collaborator

HarelM commented Nov 28, 2024

Are you sure about the places where you added the code?
It seems that equivalent format related code does not look the same.
I know this is an enum while the others are string, or number, but I find the code a bit weird...

@stanislawpuda-tomtom
Copy link
Author

stanislawpuda-tomtom commented Nov 28, 2024

I've added vertical-align to SDK support table.

Screenshot 2024-11-28 at 11 57 56

For the code, let me try to explain:

let verticalAlign = null;
if (arg['vertical-align']) { 
    // covers case, when `vertical-align` is defined with plain string, then we can check if matches enum
    if (typeof arg['vertical-align'] === 'string' && !VERTICAL_ALIGN_OPTIONS.includes(arg['vertical-align'] as VerticalAlign)) {
        return context.error(`\`vertical-align\` must be one of: 'bottom', 'center', 'top' but found '${arg['vertical-align']}' instead.`) as null;
    }

    // in this case it returns expression, so we can't check if it matches enum, only if it is string
    verticalAlign = context.parse(arg['vertical-align'], 1, StringType);
    if (!verticalAlign) return null;
}

src/expression/definitions/format.ts Outdated Show resolved Hide resolved
src/reference/v8.json Outdated Show resolved Hide resolved
@stanislawpuda-tomtom
Copy link
Author

@HarelM @lseelenbinder
Is it possible to proceed with this PR? Is there something I can do, clarify, or is there any blocker?

@@ -69,10 +70,21 @@ export class FormatExpression implements Expression {
if (!textColor) return null;
}

let verticalAlign = null;
if (arg['vertical-align']) {
if (typeof arg['vertical-align'] === 'string' && !VERTICAL_ALIGN_OPTIONS.includes(arg['vertical-align'] as VerticalAlign)) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this if be moved to the parse code to keep this as clean as the other if statements?

null,
null,
null,
section.verticalAlign ? section.verticalAlign.evaluate(ctx) : null
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this different than other properties? Why not passing null here?

@@ -1,19 +1,24 @@
import type {Color} from '../../expression/types/color';
import type {ResolvedImage} from '../types/resolved_image';

export const VERTICAL_ALIGN_OPTIONS = ['bottom', 'center', 'top'] as const;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be defined in the v8 spec file and not here?

"example": {
"syntax": {
"method": ["value", "{ \"text-font\": string, \"text-color\": color, \"font-scale\": number }", "..."],
"method": ["value", "{ \"text-font\": string, \"text-color\": color, \"font-scale\": number, \"vertical-align\": string }", "..."],
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we put enum possible values instead of string? Not sure how the handled in different places...

@HarelM
Copy link
Collaborator

HarelM commented Dec 9, 2024

I've added details on my concerns regarding the current code. Let me know if this is clearer now.

@stanislawpuda-tomtom
Copy link
Author

@HarelM It is clear - I'll cover them. Thank you!

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

Successfully merging this pull request may close these issues.

5 participants