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

[Todo] Add option to visually center icons #31

Open
dferber90 opened this issue Jul 22, 2020 · 7 comments
Open

[Todo] Add option to visually center icons #31

dferber90 opened this issue Jul 22, 2020 · 7 comments

Comments

@dferber90
Copy link

dferber90 commented Jul 22, 2020

I find myself applying style={{ transform: "translateY(-3.5%)" }} to the svg tag of the icons regularly to make them visually aligned, so they look better next to text. The percentage value depends on the image itself.

Here's an example of visual alignment applied with some text next to it for reference:

before  after
before after

At the moment, the process is quite manual if you want to achieve this:

  1. Copy icon svg markup
  2. Create an svg file locally by pasting the markup
  3. Upload that svg file to https://svgtopng.com/ to transform it to PNG
  4. Download that png file
  5. Upload the png file to https://javier.xyz/visual-center/
  6. Copy the transform percentage

An option to copy items with the visually alignment transform in place would be nice to have.

Implementation

If we were to enable the functionality mentioned above, we'd need the following steps

Modify the build process

  • use a package to convert each svg to png like (e.g. svg-to-png or svg2img)
  • use the visual-center package to find the visual center
  • store that information in some json

Modify the site

  • add a switch to toggle visual-centering mode
  • when an icon is copied attach the style object with the necessary transform

Does that sound like something you'd accept a PR for?

@dferber90
Copy link
Author

dferber90 commented Jul 22, 2020

Turns out visual-center can only run in the browser, so it's not suitable for a build-step out of the box. However, I rewrote the relevant functions locally to use node-canvas instead. With that, I was able to generate the translation values required to visually center the icons.

Here are the generated values for each icon set in the meantime:

solid
[
  {
    "path": "solid/adjustments.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/annotation.svg",
    "visualTop": 0.485,
    "visualLeft": 0.515,
    "translateXPercentage": -1.5,
    "translateYPercentage": 1.5
  },
  {
    "path": "solid/archive.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/arrow-circle-down.svg",
    "visualTop": 0.485,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 1.5
  },
  {
    "path": "solid/arrow-circle-left.svg",
    "visualTop": 0.5,
    "visualLeft": 0.51,
    "translateXPercentage": -1,
    "translateYPercentage": 0
  },
  {
    "path": "solid/arrow-circle-right.svg",
    "visualTop": 0.5,
    "visualLeft": 0.485,
    "translateXPercentage": 1.5,
    "translateYPercentage": 0
  },
  {
    "path": "solid/arrow-circle-up.svg",
    "visualTop": 0.51,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -1
  },
  {
    "path": "solid/arrow-down.svg",
    "visualTop": 0.6100000000000001,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -11
  },
  {
    "path": "solid/arrow-left.svg",
    "visualTop": 0.5,
    "visualLeft": 0.3899999999999999,
    "translateXPercentage": 11,
    "translateYPercentage": 0
  },
  {
    "path": "solid/arrow-narrow-down.svg",
    "visualTop": 0.6200000000000001,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -12
  },
  {
    "path": "solid/arrow-narrow-left.svg",
    "visualTop": 0.5,
    "visualLeft": 0.3799999999999999,
    "translateXPercentage": 12,
    "translateYPercentage": 0
  },
  {
    "path": "solid/arrow-narrow-right.svg",
    "visualTop": 0.5,
    "visualLeft": 0.6200000000000001,
    "translateXPercentage": -12,
    "translateYPercentage": 0
  },
  {
    "path": "solid/arrow-narrow-up.svg",
    "visualTop": 0.3799999999999999,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 12
  },
  {
    "path": "solid/arrow-right.svg",
    "visualTop": 0.5,
    "visualLeft": 0.6100000000000001,
    "translateXPercentage": -11,
    "translateYPercentage": 0
  },
  {
    "path": "solid/arrow-up.svg",
    "visualTop": 0.3899999999999999,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 11
  },
  {
    "path": "solid/arrows-expand.svg",
    "visualTop": 0.5,
    "visualLeft": 0.475,
    "translateXPercentage": 2.5,
    "translateYPercentage": 0
  },
  {
    "path": "solid/at-symbol.svg",
    "visualTop": 0.49,
    "visualLeft": 0.49,
    "translateXPercentage": 1,
    "translateYPercentage": 1
  },
  {
    "path": "solid/badge-check.svg",
    "visualTop": 0.49,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 1
  },
  {
    "path": "solid/ban.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/bell.svg",
    "visualTop": 0.46499999999999997,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 3.5
  },
  {
    "path": "solid/book-open.svg",
    "visualTop": 0.47,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 3
  },
  {
    "path": "solid/bookmark-alt.svg",
    "visualTop": 0.525,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -2.5
  },
  {
    "path": "solid/bookmark.svg",
    "visualTop": 0.47,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 3
  },
  {
    "path": "solid/briefcase.svg",
    "visualTop": 0.53,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -3
  },
  {
    "path": "solid/calendar.svg",
    "visualTop": 0.56,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -6
  },
  {
    "path": "solid/camera.svg",
    "visualTop": 0.515,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -1.5
  },
  {
    "path": "solid/cash.svg",
    "visualTop": 0.52,
    "visualLeft": 0.51,
    "translateXPercentage": -1,
    "translateYPercentage": -2
  },
  {
    "path": "solid/chart-bar.svg",
    "visualTop": 0.5650000000000001,
    "visualLeft": 0.5700000000000001,
    "translateXPercentage": -7,
    "translateYPercentage": -6.5
  },
  {
    "path": "solid/chart-pie.svg",
    "visualTop": 0.53,
    "visualLeft": 0.46499999999999997,
    "translateXPercentage": 3.5,
    "translateYPercentage": -3
  },
  {
    "path": "solid/chart-square-bar.svg",
    "visualTop": 0.48,
    "visualLeft": 0.475,
    "translateXPercentage": 2.5,
    "translateYPercentage": 2
  },
  {
    "path": "solid/chat-alt-2.svg",
    "visualTop": 0.42999999999999994,
    "visualLeft": 0.48,
    "translateXPercentage": 2,
    "translateYPercentage": 7
  },
  {
    "path": "solid/chat-alt.svg",
    "visualTop": 0.47,
    "visualLeft": 0.49,
    "translateXPercentage": 1,
    "translateYPercentage": 3
  },
  {
    "path": "solid/chat.svg",
    "visualTop": 0.51,
    "visualLeft": 0.49,
    "translateXPercentage": 1,
    "translateYPercentage": -1
  },
  {
    "path": "solid/check-circle.svg",
    "visualTop": 0.49,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 1
  },
  {
    "path": "solid/check.svg",
    "visualTop": 0.54,
    "visualLeft": 0.52,
    "translateXPercentage": -2,
    "translateYPercentage": -4
  },
  {
    "path": "solid/chevron-down.svg",
    "visualTop": 0.51,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -1
  },
  {
    "path": "solid/chevron-left.svg",
    "visualTop": 0.5,
    "visualLeft": 0.49,
    "translateXPercentage": 1,
    "translateYPercentage": 0
  },
  {
    "path": "solid/chevron-right.svg",
    "visualTop": 0.5,
    "visualLeft": 0.51,
    "translateXPercentage": -1,
    "translateYPercentage": 0
  },
  {
    "path": "solid/chevron-up.svg",
    "visualTop": 0.49,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 1
  },
  {
    "path": "solid/clipboard-check.svg",
    "visualTop": 0.53,
    "visualLeft": 0.495,
    "translateXPercentage": 0.5,
    "translateYPercentage": -3
  },
  {
    "path": "solid/clipboard-copy.svg",
    "visualTop": 0.525,
    "visualLeft": 0.42499999999999993,
    "translateXPercentage": 7.5,
    "translateYPercentage": -2.5
  },
  {
    "path": "solid/clipboard-list.svg",
    "visualTop": 0.54,
    "visualLeft": 0.49,
    "translateXPercentage": 1,
    "translateYPercentage": -4
  },
  {
    "path": "solid/clipboard.svg",
    "visualTop": 0.55,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -5
  },
  {
    "path": "solid/clock.svg",
    "visualTop": 0.505,
    "visualLeft": 0.485,
    "translateXPercentage": 1.5,
    "translateYPercentage": -0.5
  },
  {
    "path": "solid/cloud-download.svg",
    "visualTop": 0.44499999999999995,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 5.5
  },
  {
    "path": "solid/cloud-upload.svg",
    "visualTop": 0.45499999999999996,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 4.5
  },
  {
    "path": "solid/code.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/cog.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/collection.svg",
    "visualTop": 0.5700000000000001,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -7
  },
  {
    "path": "solid/color-swatch.svg",
    "visualTop": 0.525,
    "visualLeft": 0.4099999999999999,
    "translateXPercentage": 9,
    "translateYPercentage": -2.5
  },
  {
    "path": "solid/credit-card.svg",
    "visualTop": 0.52,
    "visualLeft": 0.515,
    "translateXPercentage": -1.5,
    "translateYPercentage": -2
  },
  {
    "path": "solid/currency-dollar.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/currency-euro.svg",
    "visualTop": 0.5,
    "visualLeft": 0.545,
    "translateXPercentage": -4.5,
    "translateYPercentage": 0
  },
  {
    "path": "solid/currency-pound.svg",
    "visualTop": 0.495,
    "visualLeft": 0.51,
    "translateXPercentage": -1,
    "translateYPercentage": 0.5
  },
  {
    "path": "solid/currency-rupee.svg",
    "visualTop": 0.525,
    "visualLeft": 0.515,
    "translateXPercentage": -1.5,
    "translateYPercentage": -2.5
  },
  {
    "path": "solid/currency-yen.svg",
    "visualTop": 0.485,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 1.5
  },
  {
    "path": "solid/cursor-click.svg",
    "visualTop": 0.545,
    "visualLeft": 0.54,
    "translateXPercentage": -4,
    "translateYPercentage": -4.5
  },
  {
    "path": "solid/desktop-computer.svg",
    "visualTop": 0.5900000000000001,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -9
  },
  {
    "path": "solid/document-add.svg",
    "visualTop": 0.5,
    "visualLeft": 0.485,
    "translateXPercentage": 1.5,
    "translateYPercentage": 0
  },
  {
    "path": "solid/document-download.svg",
    "visualTop": 0.49,
    "visualLeft": 0.48,
    "translateXPercentage": 2,
    "translateYPercentage": 1
  },
  {
    "path": "solid/document-duplicate.svg",
    "visualTop": 0.47,
    "visualLeft": 0.53,
    "translateXPercentage": -3,
    "translateYPercentage": 3
  },
  {
    "path": "solid/document-remove.svg",
    "visualTop": 0.505,
    "visualLeft": 0.485,
    "translateXPercentage": 1.5,
    "translateYPercentage": -0.5
  },
  {
    "path": "solid/document-report.svg",
    "visualTop": 0.45999999999999996,
    "visualLeft": 0.46499999999999997,
    "translateXPercentage": 3.5,
    "translateYPercentage": 4
  },
  {
    "path": "solid/document.svg",
    "visualTop": 0.515,
    "visualLeft": 0.49,
    "translateXPercentage": 1,
    "translateYPercentage": -1.5
  },
  {
    "path": "solid/dots-circle-horizontal.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/dots-horizontal.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/dots-vertical.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/download.svg",
    "visualTop": 0.6050000000000001,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -10.5
  },
  {
    "path": "solid/duplicate.svg",
    "visualTop": 0.535,
    "visualLeft": 0.535,
    "translateXPercentage": -3.5,
    "translateYPercentage": -3.5
  },
  {
    "path": "solid/emoji-happy.svg",
    "visualTop": 0.48,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 2
  },
  {
    "path": "solid/emoji-sad.svg",
    "visualTop": 0.48,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 2
  },
  {
    "path": "solid/exclamation-circle.svg",
    "visualTop": 0.51,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -1
  },
  {
    "path": "solid/exclamation.svg",
    "visualTop": 0.545,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -4.5
  },
  {
    "path": "solid/external-link.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/eye-off.svg",
    "visualTop": 0.49,
    "visualLeft": 0.515,
    "translateXPercentage": -1.5,
    "translateYPercentage": 1
  },
  {
    "path": "solid/eye.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/filter.svg",
    "visualTop": 0.3649999999999999,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 13.5
  },
  {
    "path": "solid/fire.svg",
    "visualTop": 0.56,
    "visualLeft": 0.52,
    "translateXPercentage": -2,
    "translateYPercentage": -6
  },
  {
    "path": "solid/flag.svg",
    "visualTop": 0.41999999999999993,
    "visualLeft": 0.45499999999999996,
    "translateXPercentage": 4.5,
    "translateYPercentage": 8
  },
  {
    "path": "solid/folder-add.svg",
    "visualTop": 0.515,
    "visualLeft": 0.47,
    "translateXPercentage": 3,
    "translateYPercentage": -1.5
  },
  {
    "path": "solid/folder-download.svg",
    "visualTop": 0.51,
    "visualLeft": 0.46499999999999997,
    "translateXPercentage": 3.5,
    "translateYPercentage": -1
  },
  {
    "path": "solid/folder-remove.svg",
    "visualTop": 0.515,
    "visualLeft": 0.475,
    "translateXPercentage": 2.5,
    "translateYPercentage": -1.5
  },
  {
    "path": "solid/folder.svg",
    "visualTop": 0.52,
    "visualLeft": 0.48,
    "translateXPercentage": 2,
    "translateYPercentage": -2
  },
  {
    "path": "solid/globe-alt.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/globe.svg",
    "visualTop": 0.48,
    "visualLeft": 0.49,
    "translateXPercentage": 1,
    "translateYPercentage": 2
  },
  {
    "path": "solid/hand.svg",
    "visualTop": 0.55,
    "visualLeft": 0.52,
    "translateXPercentage": -2,
    "translateYPercentage": -5
  },
  {
    "path": "solid/hashtag.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/heart.svg",
    "visualTop": 0.475,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 2.5
  },
  {
    "path": "solid/home.svg",
    "visualTop": 0.52,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -2
  },
  {
    "path": "solid/inbox-in.svg",
    "visualTop": 0.53,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -3
  },
  {
    "path": "solid/inbox.svg",
    "visualTop": 0.5700000000000001,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -7
  },
  {
    "path": "solid/information-circle.svg",
    "visualTop": 0.485,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 1.5
  },
  {
    "path": "solid/key.svg",
    "visualTop": 0.49,
    "visualLeft": 0.505,
    "translateXPercentage": -0.5,
    "translateYPercentage": 1
  },
  {
    "path": "solid/library.svg",
    "visualTop": 0.495,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0.5
  },
  {
    "path": "solid/light-bulb.svg",
    "visualTop": 0.495,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0.5
  },
  {
    "path": "solid/lightning-bolt.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/link.svg",
    "visualTop": 0.505,
    "visualLeft": 0.495,
    "translateXPercentage": 0.5,
    "translateYPercentage": -0.5
  },
  {
    "path": "solid/location-marker.svg",
    "visualTop": 0.48,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 2
  },
  {
    "path": "solid/lock-closed.svg",
    "visualTop": 0.6050000000000001,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -10.5
  },
  {
    "path": "solid/lock-open.svg",
    "visualTop": 0.6100000000000001,
    "visualLeft": 0.49,
    "translateXPercentage": 1,
    "translateYPercentage": -11
  },
  {
    "path": "solid/logout.svg",
    "visualTop": 0.5,
    "visualLeft": 0.3899999999999999,
    "translateXPercentage": 11,
    "translateYPercentage": 0
  },
  {
    "path": "solid/mail-open.svg",
    "visualTop": 0.545,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -4.5
  },
  {
    "path": "solid/mail.svg",
    "visualTop": 0.51,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -1
  },
  {
    "path": "solid/menu-alt-1.svg",
    "visualTop": 0.5,
    "visualLeft": 0.44499999999999995,
    "translateXPercentage": 5.5,
    "translateYPercentage": 0
  },
  {
    "path": "solid/menu-alt-2.svg",
    "visualTop": 0.45999999999999996,
    "visualLeft": 0.46499999999999997,
    "translateXPercentage": 3.5,
    "translateYPercentage": 4
  },
  {
    "path": "solid/menu-alt-3.svg",
    "visualTop": 0.45999999999999996,
    "visualLeft": 0.535,
    "translateXPercentage": -3.5,
    "translateYPercentage": 4
  },
  {
    "path": "solid/menu-alt-4.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/menu.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/microphone.svg",
    "visualTop": 0.49,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 1
  },
  {
    "path": "solid/minus-circle.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/moon.svg",
    "visualTop": 0.6350000000000001,
    "visualLeft": 0.32499999999999984,
    "translateXPercentage": 17.5,
    "translateYPercentage": -13.5
  },
  {
    "path": "solid/newspaper.svg",
    "visualTop": 0.53,
    "visualLeft": 0.48,
    "translateXPercentage": 2,
    "translateYPercentage": -3
  },
  {
    "path": "solid/office-building.svg",
    "visualTop": 0.485,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 1.5
  },
  {
    "path": "solid/paper-clip.svg",
    "visualTop": 0.52,
    "visualLeft": 0.475,
    "translateXPercentage": 2.5,
    "translateYPercentage": -2
  },
  {
    "path": "solid/pause.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/pencil-alt.svg",
    "visualTop": 0.51,
    "visualLeft": 0.49,
    "translateXPercentage": 1,
    "translateYPercentage": -1
  },
  {
    "path": "solid/pencil.svg",
    "visualTop": 0.53,
    "visualLeft": 0.475,
    "translateXPercentage": 2.5,
    "translateYPercentage": -3
  },
  {
    "path": "solid/phone-incoming.svg",
    "visualTop": 0.485,
    "visualLeft": 0.51,
    "translateXPercentage": -1,
    "translateYPercentage": 1.5
  },
  {
    "path": "solid/phone-outgoing.svg",
    "visualTop": 0.48,
    "visualLeft": 0.515,
    "translateXPercentage": -1.5,
    "translateYPercentage": 2
  },
  {
    "path": "solid/phone.svg",
    "visualTop": 0.5750000000000001,
    "visualLeft": 0.3799999999999999,
    "translateXPercentage": 12,
    "translateYPercentage": -7.5
  },
  {
    "path": "solid/photograph.svg",
    "visualTop": 0.43999999999999995,
    "visualLeft": 0.515,
    "translateXPercentage": -1.5,
    "translateYPercentage": 6
  },
  {
    "path": "solid/play.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/plus-circle.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/plus.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/printer.svg",
    "visualTop": 0.495,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0.5
  },
  {
    "path": "solid/puzzle.svg",
    "visualTop": 0.54,
    "visualLeft": 0.54,
    "translateXPercentage": -4,
    "translateYPercentage": -4
  },
  {
    "path": "solid/qrcode.svg",
    "visualTop": 0.49,
    "visualLeft": 0.485,
    "translateXPercentage": 1.5,
    "translateYPercentage": 1
  },
  {
    "path": "solid/question-mark-circle.svg",
    "visualTop": 0.515,
    "visualLeft": 0.49,
    "translateXPercentage": 1,
    "translateYPercentage": -1.5
  },
  {
    "path": "solid/receipt-refund.svg",
    "visualTop": 0.5,
    "visualLeft": 0.505,
    "translateXPercentage": -0.5,
    "translateYPercentage": 0
  },
  {
    "path": "solid/refresh.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/reply.svg",
    "visualTop": 0.43499999999999994,
    "visualLeft": 0.45499999999999996,
    "translateXPercentage": 4.5,
    "translateYPercentage": 6.5
  },
  {
    "path": "solid/scale.svg",
    "visualTop": 0.525,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -2.5
  },
  {
    "path": "solid/search.svg",
    "visualTop": 0.48,
    "visualLeft": 0.48,
    "translateXPercentage": 2,
    "translateYPercentage": 2
  },
  {
    "path": "solid/selector.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/share.svg",
    "visualTop": 0.5,
    "visualLeft": 0.55,
    "translateXPercentage": -5,
    "translateYPercentage": 0
  },
  {
    "path": "solid/shield-check.svg",
    "visualTop": 0.485,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 1.5
  },
  {
    "path": "solid/shield-exclamation.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/shopping-bag.svg",
    "visualTop": 0.56,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -6
  },
  {
    "path": "solid/shopping-cart.svg",
    "visualTop": 0.4149999999999999,
    "visualLeft": 0.515,
    "translateXPercentage": -1.5,
    "translateYPercentage": 8.5
  },
  {
    "path": "solid/sort-ascending.svg",
    "visualTop": 0.42999999999999994,
    "visualLeft": 0.51,
    "translateXPercentage": -1,
    "translateYPercentage": 7
  },
  {
    "path": "solid/sort-descending.svg",
    "visualTop": 0.44499999999999995,
    "visualLeft": 0.49,
    "translateXPercentage": 1,
    "translateYPercentage": 5.5
  },
  {
    "path": "solid/sparkles.svg",
    "visualTop": 0.5,
    "visualLeft": 0.51,
    "translateXPercentage": -1,
    "translateYPercentage": 0
  },
  {
    "path": "solid/speakerphone.svg",
    "visualTop": 0.49,
    "visualLeft": 0.56,
    "translateXPercentage": -6,
    "translateYPercentage": 1
  },
  {
    "path": "solid/star.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/stop.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/sun.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/support.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/switch-horizontal.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/switch-vertical.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/tag.svg",
    "visualTop": 0.45999999999999996,
    "visualLeft": 0.46499999999999997,
    "translateXPercentage": 3.5,
    "translateYPercentage": 4
  },
  {
    "path": "solid/template.svg",
    "visualTop": 0.515,
    "visualLeft": 0.475,
    "translateXPercentage": 2.5,
    "translateYPercentage": -1.5
  },
  {
    "path": "solid/terminal.svg",
    "visualTop": 0.485,
    "visualLeft": 0.52,
    "translateXPercentage": -2,
    "translateYPercentage": 1.5
  },
  {
    "path": "solid/thumb-down.svg",
    "visualTop": 0.3999999999999999,
    "visualLeft": 0.49,
    "translateXPercentage": 1,
    "translateYPercentage": 10
  },
  {
    "path": "solid/thumb-up.svg",
    "visualTop": 0.6000000000000001,
    "visualLeft": 0.505,
    "translateXPercentage": -0.5,
    "translateYPercentage": -10
  },
  {
    "path": "solid/ticket.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/translate.svg",
    "visualTop": 0.54,
    "visualLeft": 0.45499999999999996,
    "translateXPercentage": 4.5,
    "translateYPercentage": -4
  },
  {
    "path": "solid/trash.svg",
    "visualTop": 0.51,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -1
  },
  {
    "path": "solid/trending-down.svg",
    "visualTop": 0.525,
    "visualLeft": 0.5950000000000001,
    "translateXPercentage": -9.5,
    "translateYPercentage": -2.5
  },
  {
    "path": "solid/trending-up.svg",
    "visualTop": 0.47,
    "visualLeft": 0.5950000000000001,
    "translateXPercentage": -9.5,
    "translateYPercentage": 3
  },
  {
    "path": "solid/upload.svg",
    "visualTop": 0.535,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -3.5
  },
  {
    "path": "solid/user-add.svg",
    "visualTop": 0.5850000000000001,
    "visualLeft": 0.45499999999999996,
    "translateXPercentage": 4.5,
    "translateYPercentage": -8.5
  },
  {
    "path": "solid/user-circle.svg",
    "visualTop": 0.46499999999999997,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 3.5
  },
  {
    "path": "solid/user-group.svg",
    "visualTop": 0.6100000000000001,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -11
  },
  {
    "path": "solid/user-remove.svg",
    "visualTop": 0.5950000000000001,
    "visualLeft": 0.43499999999999994,
    "translateXPercentage": 6.5,
    "translateYPercentage": -9.5
  },
  {
    "path": "solid/user.svg",
    "visualTop": 0.6600000000000001,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -16
  },
  {
    "path": "solid/users.svg",
    "visualTop": 0.56,
    "visualLeft": 0.485,
    "translateXPercentage": 1.5,
    "translateYPercentage": -6
  },
  {
    "path": "solid/view-boards.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/view-grid-add.svg",
    "visualTop": 0.45999999999999996,
    "visualLeft": 0.45999999999999996,
    "translateXPercentage": 4,
    "translateYPercentage": 4
  },
  {
    "path": "solid/view-grid.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/view-list.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/volume-off.svg",
    "visualTop": 0.5,
    "visualLeft": 0.3949999999999999,
    "translateXPercentage": 10.5,
    "translateYPercentage": 0
  },
  {
    "path": "solid/volume-up.svg",
    "visualTop": 0.5,
    "visualLeft": 0.45999999999999996,
    "translateXPercentage": 4,
    "translateYPercentage": 0
  },
  {
    "path": "solid/x-circle.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/x.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "solid/zoom-in.svg",
    "visualTop": 0.43999999999999995,
    "visualLeft": 0.44499999999999995,
    "translateXPercentage": 5.5,
    "translateYPercentage": 6
  },
  {
    "path": "solid/zoom-out.svg",
    "visualTop": 0.44499999999999995,
    "visualLeft": 0.45999999999999996,
    "translateXPercentage": 4,
    "translateYPercentage": 5.5
  }
]
outline
[
  {
    "path": "outline/adjustments.svg",
    "visualTop": 0.51,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -1
  },
  {
    "path": "outline/annotation.svg",
    "visualTop": 0.41999999999999993,
    "visualLeft": 0.47,
    "translateXPercentage": 3,
    "translateYPercentage": 8
  },
  {
    "path": "outline/archive.svg",
    "visualTop": 0.42999999999999994,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 7
  },
  {
    "path": "outline/arrow-circle-down.svg",
    "visualTop": 0.52,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -2
  },
  {
    "path": "outline/arrow-circle-left.svg",
    "visualTop": 0.5,
    "visualLeft": 0.475,
    "translateXPercentage": 2.5,
    "translateYPercentage": 0
  },
  {
    "path": "outline/arrow-circle-right.svg",
    "visualTop": 0.5,
    "visualLeft": 0.52,
    "translateXPercentage": -2,
    "translateYPercentage": 0
  },
  {
    "path": "outline/arrow-circle-up.svg",
    "visualTop": 0.475,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 2.5
  },
  {
    "path": "outline/arrow-down.svg",
    "visualTop": 0.6300000000000001,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -13
  },
  {
    "path": "outline/arrow-left.svg",
    "visualTop": 0.5,
    "visualLeft": 0.3699999999999999,
    "translateXPercentage": 13,
    "translateYPercentage": 0
  },
  {
    "path": "outline/arrow-narrow-down.svg",
    "visualTop": 0.6300000000000001,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -13
  },
  {
    "path": "outline/arrow-narrow-left.svg",
    "visualTop": 0.5,
    "visualLeft": 0.3649999999999999,
    "translateXPercentage": 13.5,
    "translateYPercentage": 0
  },
  {
    "path": "outline/arrow-narrow-right.svg",
    "visualTop": 0.5,
    "visualLeft": 0.6300000000000001,
    "translateXPercentage": -13,
    "translateYPercentage": 0
  },
  {
    "path": "outline/arrow-narrow-up.svg",
    "visualTop": 0.3649999999999999,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 13.5
  },
  {
    "path": "outline/arrow-right.svg",
    "visualTop": 0.5,
    "visualLeft": 0.6300000000000001,
    "translateXPercentage": -13,
    "translateYPercentage": 0
  },
  {
    "path": "outline/arrow-up.svg",
    "visualTop": 0.3699999999999999,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 13
  },
  {
    "path": "outline/arrows-expand.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/at-symbol.svg",
    "visualTop": 0.495,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0.5
  },
  {
    "path": "outline/badge-check.svg",
    "visualTop": 0.505,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -0.5
  },
  {
    "path": "outline/ban.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/bell.svg",
    "visualTop": 0.5800000000000001,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -8
  },
  {
    "path": "outline/book-open.svg",
    "visualTop": 0.515,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -1.5
  },
  {
    "path": "outline/bookmark-alt.svg",
    "visualTop": 0.51,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -1
  },
  {
    "path": "outline/bookmark.svg",
    "visualTop": 0.52,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -2
  },
  {
    "path": "outline/briefcase.svg",
    "visualTop": 0.505,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -0.5
  },
  {
    "path": "outline/calendar.svg",
    "visualTop": 0.47,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 3
  },
  {
    "path": "outline/camera.svg",
    "visualTop": 0.535,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -3.5
  },
  {
    "path": "outline/cash.svg",
    "visualTop": 0.5,
    "visualLeft": 0.51,
    "translateXPercentage": -1,
    "translateYPercentage": 0
  },
  {
    "path": "outline/chart-bar.svg",
    "visualTop": 0.56,
    "visualLeft": 0.545,
    "translateXPercentage": -4.5,
    "translateYPercentage": -6
  },
  {
    "path": "outline/chart-pie.svg",
    "visualTop": 0.46499999999999997,
    "visualLeft": 0.535,
    "translateXPercentage": -3.5,
    "translateYPercentage": 3.5
  },
  {
    "path": "outline/chart-square-bar.svg",
    "visualTop": 0.525,
    "visualLeft": 0.525,
    "translateXPercentage": -2.5,
    "translateYPercentage": -2.5
  },
  {
    "path": "outline/chat-alt-2.svg",
    "visualTop": 0.54,
    "visualLeft": 0.54,
    "translateXPercentage": -4,
    "translateYPercentage": -4
  },
  {
    "path": "outline/chat-alt.svg",
    "visualTop": 0.45999999999999996,
    "visualLeft": 0.485,
    "translateXPercentage": 1.5,
    "translateYPercentage": 4
  },
  {
    "path": "outline/chat.svg",
    "visualTop": 0.525,
    "visualLeft": 0.47,
    "translateXPercentage": 3,
    "translateYPercentage": -2.5
  },
  {
    "path": "outline/check-circle.svg",
    "visualTop": 0.505,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -0.5
  },
  {
    "path": "outline/check.svg",
    "visualTop": 0.54,
    "visualLeft": 0.52,
    "translateXPercentage": -2,
    "translateYPercentage": -4
  },
  {
    "path": "outline/chevron-down.svg",
    "visualTop": 0.54,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -4
  },
  {
    "path": "outline/chevron-left.svg",
    "visualTop": 0.5,
    "visualLeft": 0.45499999999999996,
    "translateXPercentage": 4.5,
    "translateYPercentage": 0
  },
  {
    "path": "outline/chevron-right.svg",
    "visualTop": 0.5,
    "visualLeft": 0.54,
    "translateXPercentage": -4,
    "translateYPercentage": 0
  },
  {
    "path": "outline/chevron-up.svg",
    "visualTop": 0.45499999999999996,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 4.5
  },
  {
    "path": "outline/clipboard-check.svg",
    "visualTop": 0.515,
    "visualLeft": 0.505,
    "translateXPercentage": -0.5,
    "translateYPercentage": -1.5
  },
  {
    "path": "outline/clipboard-copy.svg",
    "visualTop": 0.52,
    "visualLeft": 0.475,
    "translateXPercentage": 2.5,
    "translateYPercentage": -2
  },
  {
    "path": "outline/clipboard-list.svg",
    "visualTop": 0.505,
    "visualLeft": 0.51,
    "translateXPercentage": -1,
    "translateYPercentage": -0.5
  },
  {
    "path": "outline/clipboard.svg",
    "visualTop": 0.45999999999999996,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 4
  },
  {
    "path": "outline/clock.svg",
    "visualTop": 0.495,
    "visualLeft": 0.515,
    "translateXPercentage": -1.5,
    "translateYPercentage": 0.5
  },
  {
    "path": "outline/cloud-download.svg",
    "visualTop": 0.51,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -1
  },
  {
    "path": "outline/cloud-upload.svg",
    "visualTop": 0.46499999999999997,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 3.5
  },
  {
    "path": "outline/code.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/cog.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/collection.svg",
    "visualTop": 0.46499999999999997,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 3.5
  },
  {
    "path": "outline/color-swatch.svg",
    "visualTop": 0.56,
    "visualLeft": 0.48,
    "translateXPercentage": 2,
    "translateYPercentage": -6
  },
  {
    "path": "outline/credit-card.svg",
    "visualTop": 0.475,
    "visualLeft": 0.49,
    "translateXPercentage": 1,
    "translateYPercentage": 2.5
  },
  {
    "path": "outline/currency-dollar.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/currency-euro.svg",
    "visualTop": 0.5,
    "visualLeft": 0.46499999999999997,
    "translateXPercentage": 3.5,
    "translateYPercentage": 0
  },
  {
    "path": "outline/currency-pound.svg",
    "visualTop": 0.505,
    "visualLeft": 0.49,
    "translateXPercentage": 1,
    "translateYPercentage": -0.5
  },
  {
    "path": "outline/currency-rupee.svg",
    "visualTop": 0.48,
    "visualLeft": 0.49,
    "translateXPercentage": 1,
    "translateYPercentage": 2
  },
  {
    "path": "outline/currency-yen.svg",
    "visualTop": 0.51,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -1
  },
  {
    "path": "outline/cursor-click.svg",
    "visualTop": 0.51,
    "visualLeft": 0.51,
    "translateXPercentage": -1,
    "translateYPercentage": -1
  },
  {
    "path": "outline/desktop-computer.svg",
    "visualTop": 0.545,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -4.5
  },
  {
    "path": "outline/document-add.svg",
    "visualTop": 0.53,
    "visualLeft": 0.49,
    "translateXPercentage": 1,
    "translateYPercentage": -3
  },
  {
    "path": "outline/document-download.svg",
    "visualTop": 0.545,
    "visualLeft": 0.49,
    "translateXPercentage": 1,
    "translateYPercentage": -4.5
  },
  {
    "path": "outline/document-duplicate.svg",
    "visualTop": 0.55,
    "visualLeft": 0.43499999999999994,
    "translateXPercentage": 6.5,
    "translateYPercentage": -5
  },
  {
    "path": "outline/document-remove.svg",
    "visualTop": 0.53,
    "visualLeft": 0.485,
    "translateXPercentage": 1.5,
    "translateYPercentage": -3
  },
  {
    "path": "outline/document-report.svg",
    "visualTop": 0.5700000000000001,
    "visualLeft": 0.505,
    "translateXPercentage": -0.5,
    "translateYPercentage": -7
  },
  {
    "path": "outline/document.svg",
    "visualTop": 0.52,
    "visualLeft": 0.48,
    "translateXPercentage": 2,
    "translateYPercentage": -2
  },
  {
    "path": "outline/dots-circle-horizontal.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/dots-horizontal.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/dots-vertical.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/download.svg",
    "visualTop": 0.6200000000000001,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -12
  },
  {
    "path": "outline/duplicate.svg",
    "visualTop": 0.45999999999999996,
    "visualLeft": 0.45499999999999996,
    "translateXPercentage": 4.5,
    "translateYPercentage": 4
  },
  {
    "path": "outline/emoji-happy.svg",
    "visualTop": 0.535,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -3.5
  },
  {
    "path": "outline/emoji-sad.svg",
    "visualTop": 0.54,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -4
  },
  {
    "path": "outline/exclamation-circle.svg",
    "visualTop": 0.485,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 1.5
  },
  {
    "path": "outline/exclamation.svg",
    "visualTop": 0.525,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -2.5
  },
  {
    "path": "outline/external-link.svg",
    "visualTop": 0.49,
    "visualLeft": 0.505,
    "translateXPercentage": -0.5,
    "translateYPercentage": 1
  },
  {
    "path": "outline/eye-off.svg",
    "visualTop": 0.48,
    "visualLeft": 0.52,
    "translateXPercentage": -2,
    "translateYPercentage": 2
  },
  {
    "path": "outline/eye.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/filter.svg",
    "visualTop": 0.4099999999999999,
    "visualLeft": 0.49,
    "translateXPercentage": 1,
    "translateYPercentage": 9
  },
  {
    "path": "outline/fire.svg",
    "visualTop": 0.54,
    "visualLeft": 0.495,
    "translateXPercentage": 0.5,
    "translateYPercentage": -4
  },
  {
    "path": "outline/flag.svg",
    "visualTop": 0.4099999999999999,
    "visualLeft": 0.47,
    "translateXPercentage": 3,
    "translateYPercentage": 9
  },
  {
    "path": "outline/folder-add.svg",
    "visualTop": 0.525,
    "visualLeft": 0.495,
    "translateXPercentage": 0.5,
    "translateYPercentage": -2.5
  },
  {
    "path": "outline/folder-download.svg",
    "visualTop": 0.535,
    "visualLeft": 0.495,
    "translateXPercentage": 0.5,
    "translateYPercentage": -3.5
  },
  {
    "path": "outline/folder-remove.svg",
    "visualTop": 0.525,
    "visualLeft": 0.49,
    "translateXPercentage": 1,
    "translateYPercentage": -2.5
  },
  {
    "path": "outline/folder.svg",
    "visualTop": 0.51,
    "visualLeft": 0.49,
    "translateXPercentage": 1,
    "translateYPercentage": -1
  },
  {
    "path": "outline/globe-alt.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/globe.svg",
    "visualTop": 0.505,
    "visualLeft": 0.505,
    "translateXPercentage": -0.5,
    "translateYPercentage": -0.5
  },
  {
    "path": "outline/hand.svg",
    "visualTop": 0.42999999999999994,
    "visualLeft": 0.475,
    "translateXPercentage": 2.5,
    "translateYPercentage": 7
  },
  {
    "path": "outline/hashtag.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/heart.svg",
    "visualTop": 0.45499999999999996,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 4.5
  },
  {
    "path": "outline/home.svg",
    "visualTop": 0.6200000000000001,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -12
  },
  {
    "path": "outline/inbox-in.svg",
    "visualTop": 0.505,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -0.5
  },
  {
    "path": "outline/inbox.svg",
    "visualTop": 0.555,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -5.5
  },
  {
    "path": "outline/information-circle.svg",
    "visualTop": 0.52,
    "visualLeft": 0.495,
    "translateXPercentage": 0.5,
    "translateYPercentage": -2
  },
  {
    "path": "outline/key.svg",
    "visualTop": 0.505,
    "visualLeft": 0.495,
    "translateXPercentage": 0.5,
    "translateYPercentage": -0.5
  },
  {
    "path": "outline/library.svg",
    "visualTop": 0.55,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -5
  },
  {
    "path": "outline/light-bulb.svg",
    "visualTop": 0.52,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -2
  },
  {
    "path": "outline/lightning-bolt.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/link.svg",
    "visualTop": 0.505,
    "visualLeft": 0.495,
    "translateXPercentage": 0.5,
    "translateYPercentage": -0.5
  },
  {
    "path": "outline/location-marker.svg",
    "visualTop": 0.475,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 2.5
  },
  {
    "path": "outline/lock-closed.svg",
    "visualTop": 0.535,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -3.5
  },
  {
    "path": "outline/lock-open.svg",
    "visualTop": 0.55,
    "visualLeft": 0.49,
    "translateXPercentage": 1,
    "translateYPercentage": -5
  },
  {
    "path": "outline/logout.svg",
    "visualTop": 0.5,
    "visualLeft": 0.4099999999999999,
    "translateXPercentage": 9,
    "translateYPercentage": 0
  },
  {
    "path": "outline/mail-open.svg",
    "visualTop": 0.5950000000000001,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -9.5
  },
  {
    "path": "outline/mail.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/menu-alt-1.svg",
    "visualTop": 0.5,
    "visualLeft": 0.43999999999999995,
    "translateXPercentage": 6,
    "translateYPercentage": 0
  },
  {
    "path": "outline/menu-alt-2.svg",
    "visualTop": 0.45499999999999996,
    "visualLeft": 0.45499999999999996,
    "translateXPercentage": 4.5,
    "translateYPercentage": 4.5
  },
  {
    "path": "outline/menu-alt-3.svg",
    "visualTop": 0.45499999999999996,
    "visualLeft": 0.54,
    "translateXPercentage": -4,
    "translateYPercentage": 4.5
  },
  {
    "path": "outline/menu-alt-4.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/menu.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/microphone.svg",
    "visualTop": 0.555,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -5.5
  },
  {
    "path": "outline/minus-circle.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/moon.svg",
    "visualTop": 0.5750000000000001,
    "visualLeft": 0.3999999999999999,
    "translateXPercentage": 10,
    "translateYPercentage": -7.5
  },
  {
    "path": "outline/newspaper.svg",
    "visualTop": 0.5,
    "visualLeft": 0.49,
    "translateXPercentage": 1,
    "translateYPercentage": 0
  },
  {
    "path": "outline/office-building.svg",
    "visualTop": 0.56,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -6
  },
  {
    "path": "outline/paper-clip.svg",
    "visualTop": 0.52,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -2
  },
  {
    "path": "outline/pause.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/pencil-alt.svg",
    "visualTop": 0.495,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0.5
  },
  {
    "path": "outline/pencil.svg",
    "visualTop": 0.49,
    "visualLeft": 0.505,
    "translateXPercentage": -0.5,
    "translateYPercentage": 1
  },
  {
    "path": "outline/phone-incoming.svg",
    "visualTop": 0.48,
    "visualLeft": 0.52,
    "translateXPercentage": -2,
    "translateYPercentage": 2
  },
  {
    "path": "outline/phone-outgoing.svg",
    "visualTop": 0.475,
    "visualLeft": 0.525,
    "translateXPercentage": -2.5,
    "translateYPercentage": 2.5
  },
  {
    "path": "outline/phone.svg",
    "visualTop": 0.545,
    "visualLeft": 0.43999999999999995,
    "translateXPercentage": 6,
    "translateYPercentage": -4.5
  },
  {
    "path": "outline/photograph.svg",
    "visualTop": 0.51,
    "visualLeft": 0.51,
    "translateXPercentage": -1,
    "translateYPercentage": -1
  },
  {
    "path": "outline/play.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/plus-circle.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/plus.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/printer.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/puzzle.svg",
    "visualTop": 0.53,
    "visualLeft": 0.53,
    "translateXPercentage": -3,
    "translateYPercentage": -3
  },
  {
    "path": "outline/qrcode.svg",
    "visualTop": 0.49,
    "visualLeft": 0.485,
    "translateXPercentage": 1.5,
    "translateYPercentage": 1
  },
  {
    "path": "outline/question-mark-circle.svg",
    "visualTop": 0.47,
    "visualLeft": 0.525,
    "translateXPercentage": -2.5,
    "translateYPercentage": 3
  },
  {
    "path": "outline/receipt-refund.svg",
    "visualTop": 0.48,
    "visualLeft": 0.49,
    "translateXPercentage": 1,
    "translateYPercentage": 2
  },
  {
    "path": "outline/refresh.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/reply.svg",
    "visualTop": 0.44999999999999996,
    "visualLeft": 0.42499999999999993,
    "translateXPercentage": 7.5,
    "translateYPercentage": 5
  },
  {
    "path": "outline/scale.svg",
    "visualTop": 0.505,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -0.5
  },
  {
    "path": "outline/search.svg",
    "visualTop": 0.49,
    "visualLeft": 0.49,
    "translateXPercentage": 1,
    "translateYPercentage": 1
  },
  {
    "path": "outline/selector.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/share.svg",
    "visualTop": 0.5,
    "visualLeft": 0.555,
    "translateXPercentage": -5.5,
    "translateYPercentage": 0
  },
  {
    "path": "outline/shield-check.svg",
    "visualTop": 0.485,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 1.5
  },
  {
    "path": "outline/shield-exclamation.svg",
    "visualTop": 0.45999999999999996,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 4
  },
  {
    "path": "outline/shopping-bag.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/shopping-cart.svg",
    "visualTop": 0.54,
    "visualLeft": 0.48,
    "translateXPercentage": 2,
    "translateYPercentage": -4
  },
  {
    "path": "outline/sort-ascending.svg",
    "visualTop": 0.3799999999999999,
    "visualLeft": 0.515,
    "translateXPercentage": -1.5,
    "translateYPercentage": 12
  },
  {
    "path": "outline/sort-descending.svg",
    "visualTop": 0.43499999999999994,
    "visualLeft": 0.485,
    "translateXPercentage": 1.5,
    "translateYPercentage": 6.5
  },
  {
    "path": "outline/sparkles.svg",
    "visualTop": 0.5,
    "visualLeft": 0.45499999999999996,
    "translateXPercentage": 4.5,
    "translateYPercentage": 0
  },
  {
    "path": "outline/speakerphone.svg",
    "visualTop": 0.49,
    "visualLeft": 0.495,
    "translateXPercentage": 0.5,
    "translateYPercentage": 1
  },
  {
    "path": "outline/star.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/stop.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/sun.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/support.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/switch-horizontal.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/switch-vertical.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/tag.svg",
    "visualTop": 0.45999999999999996,
    "visualLeft": 0.45999999999999996,
    "translateXPercentage": 4,
    "translateYPercentage": 4
  },
  {
    "path": "outline/template.svg",
    "visualTop": 0.49,
    "visualLeft": 0.505,
    "translateXPercentage": -0.5,
    "translateYPercentage": 1
  },
  {
    "path": "outline/terminal.svg",
    "visualTop": 0.515,
    "visualLeft": 0.47,
    "translateXPercentage": 3,
    "translateYPercentage": -1.5
  },
  {
    "path": "outline/thumb-down.svg",
    "visualTop": 0.46499999999999997,
    "visualLeft": 0.555,
    "translateXPercentage": -5.5,
    "translateYPercentage": 3.5
  },
  {
    "path": "outline/thumb-up.svg",
    "visualTop": 0.535,
    "visualLeft": 0.44499999999999995,
    "translateXPercentage": 5.5,
    "translateYPercentage": -3.5
  },
  {
    "path": "outline/ticket.svg",
    "visualTop": 0.5,
    "visualLeft": 0.54,
    "translateXPercentage": -4,
    "translateYPercentage": 0
  },
  {
    "path": "outline/translate.svg",
    "visualTop": 0.52,
    "visualLeft": 0.48,
    "translateXPercentage": 2,
    "translateYPercentage": -2
  },
  {
    "path": "outline/trash.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/trending-down.svg",
    "visualTop": 0.53,
    "visualLeft": 0.6200000000000001,
    "translateXPercentage": -12,
    "translateYPercentage": -3
  },
  {
    "path": "outline/trending-up.svg",
    "visualTop": 0.47,
    "visualLeft": 0.6200000000000001,
    "translateXPercentage": -12,
    "translateYPercentage": 3
  },
  {
    "path": "outline/upload.svg",
    "visualTop": 0.56,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -6
  },
  {
    "path": "outline/user-add.svg",
    "visualTop": 0.55,
    "visualLeft": 0.44499999999999995,
    "translateXPercentage": 5.5,
    "translateYPercentage": -5
  },
  {
    "path": "outline/user-circle.svg",
    "visualTop": 0.515,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -1.5
  },
  {
    "path": "outline/user-group.svg",
    "visualTop": 0.555,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -5.5
  },
  {
    "path": "outline/user-remove.svg",
    "visualTop": 0.55,
    "visualLeft": 0.4149999999999999,
    "translateXPercentage": 8.5,
    "translateYPercentage": -5
  },
  {
    "path": "outline/user.svg",
    "visualTop": 0.5700000000000001,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": -7
  },
  {
    "path": "outline/users.svg",
    "visualTop": 0.54,
    "visualLeft": 0.51,
    "translateXPercentage": -1,
    "translateYPercentage": -4
  },
  {
    "path": "outline/view-boards.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/view-grid-add.svg",
    "visualTop": 0.47,
    "visualLeft": 0.47,
    "translateXPercentage": 3,
    "translateYPercentage": 3
  },
  {
    "path": "outline/view-grid.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/view-list.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/volume-off.svg",
    "visualTop": 0.5,
    "visualLeft": 0.46499999999999997,
    "translateXPercentage": 3.5,
    "translateYPercentage": 0
  },
  {
    "path": "outline/volume-up.svg",
    "visualTop": 0.5,
    "visualLeft": 0.515,
    "translateXPercentage": -1.5,
    "translateYPercentage": 0
  },
  {
    "path": "outline/x-circle.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/x.svg",
    "visualTop": 0.5,
    "visualLeft": 0.5,
    "translateXPercentage": 0,
    "translateYPercentage": 0
  },
  {
    "path": "outline/zoom-in.svg",
    "visualTop": 0.44999999999999996,
    "visualLeft": 0.45499999999999996,
    "translateXPercentage": 4.5,
    "translateYPercentage": 5
  },
  {
    "path": "outline/zoom-out.svg",
    "visualTop": 0.45499999999999996,
    "visualLeft": 0.47,
    "translateXPercentage": 3,
    "translateYPercentage": 4.5
  }
]

These can be used to manually apply a transform which vertically aligns the icons until the functionality eventually makes it into the site itself (if that is welcome). To use these, apply translateXPercentage and translateXPercentage in a style attribute like so :

<svg style={{ transform: `translate(${translateXPercentage}%, ${translateXPercentage}%)`  }} />

for example

<svg style={{ transform: `translate(0%, -10%)`  }} />

@dferber90 dferber90 changed the title Visual Alignment option Visual Center option Jul 22, 2020
@zaydek
Copy link
Owner

zaydek commented Jul 29, 2020

Hey Dominik, this is pretty interesting. Thank you for creating an issue and documenting your experience.

If anything I think this could be added as a feature for framework libraries. The viewer could support inline transforms but I think you would agree that this is the kind of thing that can get messy over time.

If anything I would recommend creating this issue for the original repo so this can potentially get traction on a library-level.

For your use case, if you’re not doing this already, I’d recommend doing something like this:

<svg style={visualCenter("lock")} ...>

Which would expand to your precomputed styles. Then the only thing you need to remember / maintain is icon identity, like which icon you are referring to at any given time.

Does that make sense?

This could potentially be made to be an option for this repo but I don’t have the time right now to roll this feature myself.

@dferber90
Copy link
Author

dferber90 commented Aug 13, 2020

I wanted to offer the suggestion in case you felt like it's a good addition to the website. It doesn't seem like many people are visually centering their icons, so I agree that it isn't worth the additional effort.

As writing the script to get the right values out was a bit tricky, I thought I'd share the results. Coming back to this issue to check the precomputed values has been good enough for the few times I needed it.

Thanks for your consideration and your thoughtful response 👍

For the sake of completeness, I'll leave the code used to generate the initial values here

You can copy this file into a fresh clone of the heroicons repo, install the required npm packages (npm install svg2png klaw canvas lodash) and execute node get-visual-centers.js

It will then write centers-outline.json or centers-solid.json depending on what you've set as const input = inputs.outline; in the script. I didn't complete the script to accept cli args.

const fs = require("fs");
const svg2png = require("svg2png");
const path = require("path");
const klaw = require("klaw");
const { createCanvas, loadImage } = require("canvas");
const _ = require("lodash");

const inputs = {
  outline: {
    name: "outline",
    size: 24 * 21,
    source: "./outline",
  },
  solid: {
    name: "solid",
    size: 20 * 21,
    source: "./solid",
  },
};

const output = {
  emitFile: true,
  log: true,
};

// CHANGE THIS
// chose between input.solid and input.outline
const input = inputs.outline;

const COLOR_DIFF_WEIGHT_EXPO = 0.333;

const ROUNDS = 200;

function visualCenter(base64, callback, opts = {}) {
  base64ImageToRGBMatrix(
    base64,
    (err, rgbMatrix) => {
      const height = rgbMatrix.length;
      const width = rgbMatrix[0].length;
      const bgColor = normalizeColor(rgbMatrix[0][0]);

      const { visualLeft, visualTop } = calculateVisualCenter(rgbMatrix);

      callback(null, {
        visualTop: visualTop,
        visualLeft: visualLeft,

        bgColor: bgColor,
        width: width,
        height: height,
      });
    },
    {
      size: input.size,
    }
  );
}

function calculateVisualCenter(rgbMatrix) {
  var visualLeft = 0.5;
  var visualTop = 0.5;

  var { visualLeft } = recursiveGetCoord(
    rgbMatrix,
    visualLeft,
    visualTop,
    "X",
    1 / ROUNDS
  );
  var { visualLeft } = recursiveGetCoord(
    rgbMatrix,
    visualLeft,
    visualTop,
    "X",
    -1 / ROUNDS
  );
  var { visualTop } = recursiveGetCoord(
    rgbMatrix,
    visualLeft,
    visualTop,
    "Y",
    1 / ROUNDS
  );
  var { visualTop } = recursiveGetCoord(
    rgbMatrix,
    visualLeft,
    visualTop,
    "Y",
    -1 / ROUNDS
  );

  return { visualLeft, visualTop };
}

function recursiveGetCoord(
  rgbMatrix,
  visualLeft,
  visualTop,
  currentAxis,
  stepSize
) {
  const bgColor = normalizeColor(rgbMatrix[0][0]);
  const height = rgbMatrix.length;
  const width = rgbMatrix[0].length;

  var visualLeftToApply = visualLeft;
  var visualTopToApply = visualTop;

  const ops = {
    bgColor,
    height: rgbMatrix.length,
    width: rgbMatrix[0].length,
    maxDiff:
      Math.max(bgColor.r, 255 - bgColor.r) +
      Math.max(bgColor.g, 255 - bgColor.g) +
      Math.max(bgColor.b, 255 - bgColor.b),
    maxDistance: getDistance([0, 0], [width, height]),
  };

  var newVisualLeft = visualLeft;
  var newVisualTop = visualTop;

  if (currentAxis === "X") {
    newVisualLeft += stepSize;
  } else {
    newVisualTop += stepSize;
  }

  var oldCenterIntensity = getCenterIntensity(
    rgbMatrix,
    visualLeft,
    visualTop,
    ops
  );
  var newCenterIntensity = getCenterIntensity(
    rgbMatrix,
    newVisualLeft,
    newVisualTop,
    ops
  );

  while (newCenterIntensity > oldCenterIntensity) {
    visualLeftToApply = newVisualLeft;
    visualTopToApply = newVisualTop;

    if (currentAxis === "X") {
      newVisualLeft += stepSize;
    } else {
      newVisualTop += stepSize;
    }
    oldCenterIntensity = newCenterIntensity;
    newCenterIntensity = getCenterIntensity(
      rgbMatrix,
      newVisualLeft,
      newVisualTop,
      ops
    );
  }

  return {
    visualLeft: visualLeftToApply,
    visualTop: visualTopToApply,
  };
}

function getCenterIntensity(rgbMatrix, visualLeft, visualTop, ops) {
  const { bgColor, height, width, maxDiff, maxDistance } = ops;

  const centerCol = visualTop * height;
  const centerRow = visualLeft * width;
  const centerPoint = [centerCol, centerRow];

  return _.reduce(
    rgbMatrix,
    (resRow, row, rowIdx) => {
      return (
        resRow +
        _.reduce(
          row,
          (resCol, col, colIdx) => {
            const cellColorDiff = rgbDiff(bgColor, col, maxDiff);

            if (!cellColorDiff) return resCol;

            const cellDistance = getDistance(centerPoint, [rowIdx, colIdx]);
            const cellColorWeight =
              cellColorDiff *
              Math.pow(1 - cellDistance / maxDistance, 0.5) *
              1000;

            return resCol + cellColorWeight;
          },
          0
        )
      );
    },
    0
  );
}

function getDistance(pointA, pointB) {
  return Math.pow(
    Math.pow(pointA[0] - pointB[0], 2) + Math.pow(pointA[1] - pointB[1], 2),
    0.5
  );
}

function normalizeColor(color) {
  return {
    r: Math.floor(color.r * (color.a / 255) + 255 * (1 - color.a / 255)),
    g: Math.floor(color.g * (color.a / 255) + 255 * (1 - color.a / 255)),
    b: Math.floor(color.b * (color.a / 255) + 255 * (1 - color.a / 255)),
    a: 255,
  };
}

function rgbDiff(baseColor, testColor, maxDiff) {
  if (testColor.a === 0) return 0;

  const diff =
    Math.abs(baseColor.r - testColor.r) +
    Math.abs(baseColor.g - testColor.g) +
    Math.abs(baseColor.b - testColor.b);
  const result =
    Math.pow(diff / maxDiff, COLOR_DIFF_WEIGHT_EXPO) *
    (testColor.a / 255) *
    1000;

  return result;
}

// -----------------------------------------------------------------------------
// https://github.com/javierbyte/base64-image-utils/blob/3e1c7fa27126ccfe751005eedbe39cb7d2f6391a/lib/base64ImageToRGBMatrix.js

// const { createWorker } = require("./utils");

const base64ImageToRGBMatrix = function (base64, callback, opts = {}) {
  loadImage(base64).then((img) => {
    let resizeRatio = 1;

    if (opts.size) {
      resizeRatio = opts.size / Math.max(img.width, img.height);
    }

    if (opts.maxSize) {
      if (img.width > opts.maxSize || img.height > opts.maxSize) {
        resizeRatio = opts.maxSize / Math.max(img.width, img.height);
      }
    }

    const canvas = createCanvas(img.width, img.height);

    canvas.width = Math.floor(img.width * resizeRatio);
    canvas.height = Math.floor(img.height * resizeRatio);

    const ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0, canvas.width, canvas.height);

    const { data } = ctx.getImageData(
      0,
      0,
      ctx.canvas.width,
      ctx.canvas.height
    );

    const { width, height } = canvas;

    let result = [];
    for (var y = 0; y < height; y++) {
      result[y] = [];
      for (var x = 0; x < width; x++) {
        result[y][x] = {
          r: data[y * width * 4 + x * 4],
          g: data[y * width * 4 + x * 4 + 1],
          b: data[y * width * 4 + x * 4 + 2],
          a: data[y * width * 4 + x * 4 + 3],
        };
      }
    }

    callback(null, result);
  });
};

// -----------------------------------------------------------------------------
function toPercent(number) {
  return Math.round(number * 10000) / 100;
}

const items = []; // files, directories, symlinks, etc

klaw(input.source)
  .on("data", (item) => {
    if (!item.path.endsWith(".svg")) return;
    // if (!item.path.endsWith("lock-closed.svg")) return;
    // if (items.length > 0) return;
    items.push(
      (async () => {
        try {
          const svg = fs.readFileSync(item.path, "utf8");
          const data = await svg2png(svg, {
            width: input.size,
            height: input.size,
          });

          // fs.writeFileSync(item.path + ".png", data);

          const center = await new Promise((resolve, reject) => {
            visualCenter(data, function (err, result) {
              if (err) reject(err);
              else resolve(result);
              /*
              results in an object with the data as:
                {
                  visualTop: <Visual center for Y axis, from 0 to 1>
                  visualLeft: <Visual center for X axis, from 0 to 1>
                  bgColor: <The background color that we detected>
                  width: <The width of the image>
                  height: <The height of the image>
                }
            */
            });
          });
          return {
            path: path.relative(__dirname, item.path),
            visualTop: center.visualTop,
            visualLeft: center.visualLeft,
            translateXPercentage: toPercent(1 - center.visualLeft - 0.5),
            translateYPercentage: toPercent(1 - center.visualTop - 0.5),
          };
        } catch (e) {
          console.log(e);
        }
      })()
    );
  })
  .on("end", async () => {
    const result = await Promise.all(items);

    if (output.emitFile)
      fs.writeFileSync(
        `./centers-${input.name}.json`,
        JSON.stringify(result, null, 2),
        "utf8"
      );

    if (output.log) console.log(result);
  });

I copied some functions from https://github.com/javierbyte/base64-image-utils to make the script work inside node (where we don't have canvas).

@zaydek
Copy link
Owner

zaydek commented Aug 15, 2020

I’m actually going to keep this open (as a reminder for me) because I want to add this feature at a later time.

Thanks for all your hard work. ❤️

@zaydek zaydek reopened this Aug 15, 2020
@zaydek zaydek changed the title Visual Center option [Todo] Add option to visually center icons Aug 15, 2020
@zaydek
Copy link
Owner

zaydek commented Jan 8, 2023

@dferber90 I'd love to get this implemented now that I've just pulled off a major refactor. Do you have a JSON artifact or or something similar? I do see the script you included.

@dferber90
Copy link
Author

@zaydek unfortunately not anymore, I think this got lost when I switched laptops. Either way it would be outdated since new heroicons were since I last used this script. You should be able to run the script to create the necessary files though 🤞

@zaydek
Copy link
Owner

zaydek commented Jan 9, 2023

@dferber90 Ah good point. OK will follow-up here when I make progress on this front. Thank you for your work. :)

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

No branches or pull requests

2 participants