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

Browse icons as svg #5080

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open

Conversation

mmd-osm
Copy link
Collaborator

@mmd-osm mmd-osm commented Aug 15, 2024

The browse icons haven't been updated for quite some time and are still served as PNG icons. As the icons should reflect the current carto style, I copied a fair amount to this PR, and added some coloring similar to amenity-points.mss.

One of the design goals for the conversion was to use osm-carto svg files as-is, and at the same time use svg files as < img >, rather than inlining them. This has some implications on coloring: color values need to be translated to a filter, for which i used https://blog.union.io/code/2017/08/10/img-svg-fill/ + https://stackoverflow.com/questions/24933430/img-src-svg-changing-the-styles-with-css/52041765#52041765

Before converting more icons in browse.scss + common.scss, I wanted to get some feedback if the overall approach is sound. As an example, for the fill parameter I tried "#666666" as parameter value, as well as the original color descriptions from osm-cargo (e.g. "amenity-brown"). I find the latter a bit easier to understand.

Please take a look, and let me know how we should proceed.

image

image

@AntonKhorev
Copy link
Collaborator

AntonKhorev commented Aug 15, 2024

As the icons should reflect the current carto style

Should they? How about landuses, for example?

@mmd-osm
Copy link
Collaborator Author

mmd-osm commented Aug 15, 2024

I believe the current icons originate from osm-carto, and are mostly 9-10 years old. In the meantime, carto has moved from png to svg, and updated some of their icons. In a way, this PR is catching up with changes in the default style.

Landuse is a good question. I would do them in a second step, once the node icons have been migrated to svg. We don't have to do everything at once.

@AntonKhorev
Copy link
Collaborator

use svg files as < img >, rather than inlining them

Why not inline <symbol>/<use> with colors defined as css custom properties, which you can redefine in dark mode?

@mmd-osm
Copy link
Collaborator Author

mmd-osm commented Aug 15, 2024

This seems like a good idea. Would you use some Gem for it, like https://github.com/jamesmartin/inline_svg and change the browse view / browse_helper.rb accordingly? Do we already have something similar in the code base today, which we could reuse?

@mmd-osm mmd-osm force-pushed the patch/browsesvg branch 4 times, most recently from 83483af to 983f066 Compare August 15, 2024 14:00
@mmd-osm
Copy link
Collaborator Author

mmd-osm commented Aug 15, 2024

@AntonKhorev : Just for clarification: is this the approach you had in mind? https://stackoverflow.com/a/68569598/3501889

It seems the target svg need to include a "fragment identifier" to make this work, which is currently not the case for the carto svg files. See https://stackoverflow.com/a/72140723/3501889
That's not really a big issue, we can completely automate this step.

I tried these changes in a browser window by adding the svg to the DOM, and it works fine. Changing colors is also much easier now.

By the way, the inline_svg gem is loading the file when rendering the page and injecting the contents into the HTML document, which is not great for caching.

@mmd-osm mmd-osm force-pushed the patch/browsesvg branch 4 times, most recently from b6cea61 to 61867fc Compare August 15, 2024 19:35
@AntonKhorev
Copy link
Collaborator

I wanted inline svg with a bunch of <symbol>s added once to every browse page and inline svgs with <use>s referring to these symbols. I wanted to try this approach with routing icons first because there are fewer of them. I partially did this in #4901:

<svg width="20" height="20" class="d-none">
<symbol id="routing-sprite-start" fill="none" stroke="currentColor" stroke-width="2">
<path d="M10 16 a1 1 0 1 0 0 -2 1 1 0 1 0 0 2 m0 -4 v-8 m2.5 2 l-2.5 -2.5 -2.5 2.5 z" />
</symbol>
<symbol id="routing-sprite-destination" fill="none" stroke="currentColor" stroke-width="2">
<path d="M10 5 a1 1 0 1 0 0 -2 1 1 0 1 0 0 2 m0 12 v-8 m2.5 2 l-2.5 -2.5 -2.5 2.5 z" />
</symbol>
<symbol id="routing-sprite-straight" fill="none" stroke="currentColor" stroke-width="2">
<path d="M10 17 v-13 m2.5 2 l-2.5 -2.5 -2.5 2.5 z" />
</symbol>
<symbol id="routing-sprite-slight-right" fill="none" stroke="currentColor" stroke-width="2">
<path d="M7 17 v-3 q0 -2 2 -4 l5 -5 m0 0 h-3 l3 3 z" />
</symbol>
<symbol id="routing-sprite-right" fill="none" stroke="currentColor" stroke-width="2">
<path d="M8 17 v-5 q0 -3 3 -3 h4 m-2 2.5 l2.5 -2.5 -2.5 -2.5 z" />
</symbol>
<symbol id="routing-sprite-sharp-right" fill="none" stroke="currentColor" stroke-width="2">
<path d="M8 17 v-7 q0 -6 6 0 l2 2 m0 0 v-3 l-3 3 z" />
</symbol>
<symbol id="routing-sprite-u-turn" fill="none" stroke="currentColor" stroke-width="2">
<path d="M16 17 v-7 a4.5 4.5 0 0 0 -9 0 v5 m-2.5 -2 l2.5 2.5 2.5 -2.5 z" />
</symbol>
<symbol id="routing-sprite-slight-left" fill="none" stroke="currentColor" stroke-width="2">
<path d="M13 17 v-3 q0 -2 -2 -4 l-5 -5 m0 0 h3 l-3 3 z" />
</symbol>
<symbol id="routing-sprite-left" fill="none" stroke="currentColor" stroke-width="2">
<path d="M13 17 v-5 q0 -3 -3 -3 h-4 m2 2.5 l-2.5 -2.5 2.5 -2.5 z" />
</symbol>
<symbol id="routing-sprite-sharp-left" fill="none" stroke="currentColor" stroke-width="2">
<path d="M13 17 v-7 q0 -6 -6 0 l-2 2 m0 0 v-3 l3 3 z" />
</symbol>
<symbol id="routing-sprite-roundabout" fill="none" stroke="currentColor" stroke-width="2">
<path d="M8 17 v-3 a 3 3 0 1 0 0 -6 3 3 0 1 0 0 6 m2 -4 l5 -5 m0 0 h-3 l3 3 z" />
</symbol>
<symbol id="routing-sprite-fork-right" fill="none" stroke="currentColor" stroke-width="2">
<path d="M9 14 q0 -2 -2 -4 l-3 -3" opacity=".5" />
<path d="M9 17 v-3 q0 -2 2 -4 l5 -5 m0 0 h-3 l3 3 z" />
</symbol>
<symbol id="routing-sprite-fork-left" fill="none" stroke="currentColor" stroke-width="2">
<path d="M11 14 q0 -2 2 -4 l3 -3" opacity=".5" />
<path d="M11 17 v-3 q0 -2 -2 -4 l-5 -5 m0 0 h3 l-3 3 z" />
</symbol>
<symbol id="routing-sprite-merge-left" fill="none" stroke="currentColor" stroke-width="2">
<path d="M8 7 q0 2 -2 4 l-3 3" opacity=".5" />
<path d="M8 4 v3 q0 2 2 4 l5 5 m-5 -5 h3 l-3 3 z" />
</symbol>
<symbol id="routing-sprite-merge-right" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 7 q0 2 2 4 l3 3" opacity=".5" />
<path d="M12 4 v3 q0 2 -2 4 l-5 5 m5 -5 h-3 l3 3 z" />
</symbol>
<symbol id="routing-sprite-end-of-road-right" fill="none" stroke="currentColor" stroke-width="2">
<path d="M2 9 h10" opacity=".5" />
<path d="M9 17 v-5 q0 -3 3 -3 h4 m-2 2.5 l2.5 -2.5 -2.5 -2.5 z" />
</symbol>
<symbol id="routing-sprite-end-of-road-left" fill="none" stroke="currentColor" stroke-width="2">
<path d="M18 9 h-10" opacity=".5" />
<path d="M11 17 v-5 q0 -3 -3 -3 h-4 m2 2.5 l-2.5 -2.5 2.5 -2.5 z" />
</symbol>
<symbol id="routing-sprite-exit-right" fill="none" stroke="currentColor" stroke-width="2">
<path d="M9 14 v-8" opacity=".5" />
<path d="M9 17 v-3 q0 -2 2 -4 l5 -5 m0 0 h-3 l3 3 z" />
</symbol>
<symbol id="routing-sprite-exit-left" fill="none" stroke="currentColor" stroke-width="2">
<path d="M11 14 v-8" opacity=".5" />
<path d="M11 17 v-3 q0 -2 -2 -4 l-5 -5 m0 0 h3 l-3 3 z" />
</symbol>
<symbol id="routing-sprite-ferry" fill="none" stroke="currentColor" stroke-width="1">
<path d="M10.5 8 l-6 2 l2.5 2 v1.5 a2.828 2.828 0 0 1 1.5 1 a2.828 2.828 0 0 1 4 0 a2.828 2.828 0 0 1 1.5 -1 v-1.5 l2.5 -2 z" fill="currentColor" />
<path d="M6.5 9.5 v-5 h8 v5 m-5.5 -6 h3" />
<path d="M5.5 16.5 a1.414 2.828 0 0 1 2 0 a1.414 2.828 0 0 0 2 0 a1.414 2.828 0 0 1 2 0 a1.414 2.828 0 0 0 2 0 a1.414 2.828 0 0 1 2 0" />
</symbol>
</svg>

@mmd-osm
Copy link
Collaborator Author

mmd-osm commented Aug 16, 2024

Thank you for the details the inline approach! I think it would be a bit challenging to always include all symbol svg files in the browse page due to their total size (around 200K).

I thought about adding some configuration table to move most of the logic from browse.scss to a yml file (at least for svg). For this purpose I have introduced a new config/browse_image.yml, and the corresponding initializer in config/initializers/browse_image.rb. (see most recent push).

In some cases the same image is used for different tags, so we would need some sort of configuration anyway to map tags to svg images and define how they should be filled.

irb(main):001> BROWSE_IMAGE["shop_pet".to_sym]
=> {:image=>"shop_pet.svg", :fill=>"shop"}

In the next step BROWSE_IMAGE can then be used in helpers/browse_helper.rb to find out if an SVG exists for a "{key}_{value}", and then use the external_svg approach I mentioned in my previous post.

In browse_helper.rb something similar to the following would be needed. Also, we would need to define some css classes for the new svg images.

      elem_icon = icon_tags(object).map { |k, v| "#{k}_#{v}" }.last
      elem_icon_detail = BROWSE_IMAGE[elem_icon.to_sym]
      external_svg(elem_icon_detail[:image], elem_icon_detail[:fill]) if elem_icon_detail
  def external_svg(identifier, fill, attributes = {})
    file_name, fragment = identifier.split("#")
    fragment ||= "icon"
    attributes[:xmlns] = "http://www.w3.org/2000/svg"
    attributes[:class] = fill
    file_name = "browse/#{file_name}"
    content_tag :svg, attributes do
      tag.use :href => "#{image_path(file_name)}##{fragment}"
    end
  end

@mmd-osm mmd-osm force-pushed the patch/browsesvg branch 7 times, most recently from d772ead to 0fcdb3d Compare August 16, 2024 16:58
@mmd-osm
Copy link
Collaborator Author

mmd-osm commented Aug 16, 2024

I believe the code should be good for another review. The screenshot below shows mixed svg/png rendering (1 png, rest is svg). The exact symbol location probably need some further tweaking in CSS. Also, the code in browser_helper.rb might need some improvements. Focus right now should be that we're ok with the approach.

image

@mmd-osm mmd-osm marked this pull request as ready for review August 16, 2024 20:03
@mmd-osm mmd-osm force-pushed the patch/browsesvg branch 2 times, most recently from 96ae532 to eb714c5 Compare August 18, 2024 08:23
@AntonKhorev
Copy link
Collaborator

I think it would be a bit challenging to always include all symbol svg files in the browse page due to their total size (around 200K).

If they specify path coordinates to a millionth fraction of a pixel, it's not surprising.

@mmd-osm
Copy link
Collaborator Author

mmd-osm commented Aug 28, 2024

@AntonKhorev : I think I'm done now with my changes. Anything else we need to check before merging?

@AntonKhorev
Copy link
Collaborator

AntonKhorev commented Sep 21, 2024

Some icons before/after in dark mode:

image image ; image image ; image image

  • some icons are too dark, I inverted and hue-rotated them; here it's not done I suppose; see place_of_worship icon for an extreme example
  • gate icon has white background
  • do we need a smaller icon for waste baskets here just because it's smaller on the map render?
  • alignment wasn't great before, here it's even worse, see traffic lights for example

margin-left: -25px;
width: 25px;
height: 18px;
/*rtl:ignore*/ transform: translate(2px, 0px);
Copy link
Collaborator

Choose a reason for hiding this comment

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

What's this translate for?

Old css background image above, new svg image below:
image

Copy link
Collaborator Author

@mmd-osm mmd-osm Sep 21, 2024

Choose a reason for hiding this comment

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

The purpose of the translate is to improve the positioning of SVGs. Like I've written below, that's good for the majority of new SVGs.

The remaining ~20 old PNG symbols will be replaced by SVGs in later PRs, by which time this PNG/SVG positioning issue will become obsolete. The transition to SVGs clearly has the higher priority for me.

If someone feels like working on it, some fine tuning could still be done in follow up PRs.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

highway=turning_circle has been replaced by an SVG symbol.

@AntonKhorev
Copy link
Collaborator

I still think it's easier to switch to <img>s first, then start replacing them with svgs, assuming all of the images have the same size. Hopefully we can avoid random pixel offsets in css.

@mmd-osm
Copy link
Collaborator Author

mmd-osm commented Sep 21, 2024

Thank you for reviewing this PR another time.

some icons are too dark, I inverted and hue-rotated them; here it's not done I suppose; see place_of_worship icon for an extreme example

Agree, that's also something I've noticed. I'm pushing another commit now which should improve the situation. As a general remark, I would leave that sort of fine tuning to a follow up pull request.

do we need a smaller icon for waste baskets here just because it's smaller on the map render?

Yes, it matches exactly the size you see on the map.

alignment wasn't great before, here it's even worse, see traffic lights for example

I've checked all 219 SVGs, and found that less than 10 of them might need some fine tuning. The vast majority of new SVGs is just fine. Hence, I think that's a good topic for follow up pull requests as well.

I still think it's #5080 (comment) to switch to s first, then start replacing them with svgs, assuming all of the images have the same size. Hopefully we can avoid random pixel offsets in css.

I'm not entirely clear what you're suggesting here. Assuming we need to convert SVGs to PNGs and maintain new entries in browse.scss for them, that would be a very clear no-go for me. Speaking of experience in this PR, it's creating a huge effort with very limited options for later reuse.

I would suggest to focus on any remaining important issues with SVGs instead in this PR, rather than spending time on PNGs which we want to phase out anyway.

@AntonKhorev
Copy link
Collaborator

do we need a smaller icon for waste baskets here just because it's smaller on the map render?

Yes, it matches exactly the size you see on the map.

No, we don't need it to match exactly the size you see on the (one particular rendering of the) map. We need to decide what size the icons should be and make them that size.

@AntonKhorev
Copy link
Collaborator

I've checked all 219 SVGs, and found that less than 10 of them might need some fine tuning. The vast majority of new SVGs is just fine.

Why making a pull request with 219 svgs with the vast majority just fine instead of a smaller pull request with all svg fine?

@AntonKhorev
Copy link
Collaborator

Assuming we need to convert SVGs to PNGs

I'm not suggesting that.

@mmd-osm
Copy link
Collaborator Author

mmd-osm commented Sep 22, 2024

I've added dedicated css formatting for 9 SVG symbols now, to improve positioning and/or size of the respective symbols. Maybe you could take another look now. If necessary, please suggest exactly which symbol should be changed and how.

The approach should be flexible enough to allow for further fine-tuning in the future.

@mmd-osm
Copy link
Collaborator Author

mmd-osm commented Sep 30, 2024

Assuming we need to convert SVGs to PNGs

I'm not suggesting that.

Ok, I think you would need to further elaborate on your proposal, because it’s still not clear to me how this looks in detail. Please provide some working code snippets which addresses both position and coloring of svg. Also some comment why it is better or what issues it solves. We can then look into this in more detail and work out the best approach.

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

Successfully merging this pull request may close these issues.

2 participants