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 19 commits into
base: master
Choose a base branch
from
Open

Conversation

mmd-osm
Copy link
Contributor

@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
Contributor 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
Contributor 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
Contributor 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
Contributor 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
Contributor 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
Contributor 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.

@mmd-osm
Copy link
Contributor Author

mmd-osm commented Oct 21, 2024

Here's another comparison at 250% zoom. The old rendering looked a bit off, in particular for the (part of ways...) section.

Old New
old1 new1

As mentioned earlier, the new icons + colors are based on https://wiki.openstreetmap.org/wiki/OpenStreetMap_Carto/Symbols. It is expected that some of them differ from the old ones.

Rescale golf svgs to 14
Multiple icons can be stored in a single .svg file, with #... denoting the
respective icon.
Copy link

1 Warning
⚠️ Number of updated lines of code is too large to be in one PR. Perhaps it should be separated into two or more?

Generated by 🚫 Danger

@AntonKhorev
Copy link
Collaborator

Ok, I think you would need to further elaborate on your proposal

#5385 as a first step in replacing css backgrounds with images. See how I only use one pixel value of 20px / 1.25rem.

The old rendering looked a bit off, in particular for the (part of ways...) section.

Part of ways I'd do them completely differently, see #5317.

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

Successfully merging this pull request may close these issues.

2 participants