Как стать автором
Обновить

Комментарии 23

Супер, но разве хранить геометрию в атрибуте не излишне? Это же рефлексия для извлечения. Просто вопрос, если что

Это один из вариантов хранения в C#-коде, когда всё в одном месте (обозримость, легкая правка). Для меня было главное - уйти от ресурсов в XAML и как-то автоматизировать включение фрагментов SVG-файла в свой код. Возможно, не самый оптимальный вариант. Что можете предложить взамен?

Эти вопросы я больше для себя задаю, чтобы лучше понимать тему, спасибо за ответ!

Мы решали подобную задачку в EMXControls. Сделали сборку для векторных иконок. На source generator создаем из названий файлов специальный класс свойства которого называются так же как иконки. За счет этого работают подсказки в VisualStudio и невозможно использовать иконку которой нет в наборе. В коде получается вот так

Eremex.AvaloniaUI.Icons.Basic.Question

в xaml

Glyph="{x:Static icons:Basic.Question}"

для раскраски иконок используем css

Как нибудь напишем статью об этом.

для раскраски иконок используем css

А это как сделать в Avalonia?

Svg.Css - это attached inherited свойство. Работает на поддерево.

Спасибо, посмотрю как они это реализовали. Только для нашего случая, наверно, будет тяжеловато. И по рендерингу, и по программной реализации.

Пример подсказок Visual Studio
Пример подсказок Visual Studio

Согласен, при помощи класса тоже хороший вариант. Для моей реализации подсказки в дизайнере Visual Studio тоже работают, причем без {x:Static} и, что удивительно, даже namespace не надо указывать.

upd: Компилятор тоже не даст указать несуществующую айконку.

На момент написания статьи большинство (2070 из 2074) Bootstrap Icons используют для отрисовки исключительно элементы <path> (не задействуют <circle><rect>)

Если кому интересно, на сейчас из 2078 иконок, богопротивные элементы circle и rect есть в следующих файлах:

align-bottom
align-top
circle-fill
dice-1

ПыСы Извините, немного вопрос не по окладу: а почему "айконка", а не "иконка"?

Абсолютно точно, именно эти 4 штуки мне кровь портили.
Поэтому я в своем генераторе их переопределяю.

{
  "align-bottom": [
    "M6 1h4a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1z",
    "M1.5 14a.5.5 0 0 0 0 1zm13 1a.5.5 0 0 0 0-1zm-13 0h13v-1h-13z"
  ],
  "align-top": [
    "M6 15h4a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H6a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1z",
    "M1.5 2a.5.5 0 0 1 0-1zm13-1a.5.5 0 0 1 0 1zm-13 0h13v1h-13z"
  ],
  "circle-fill": [
    "M16 8A8 8 0 1 1 0 8A8 8 0 1 1 16 8Z"
  ],
  "dice-1": [
    "M9.5 8a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z",
    "M13 1a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2zM3 0a3 3 0 0 0-3 3v10a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V3a3 3 0 0 0-3-3z"
  ]
}

Результат работы генератора:

> path-icons@0.0.13 update-bi D:\Git\path-icons
> node build/update-bi-json.mjs --verbose

Starting Bootstrap Icons JSON build...
Found 2078 SVG file(s) to process from D:\Git\path-icons\node_modules\bootstrap-icons\icons
  WARN: Skipping align-bottom.svg. Contains disallowed element type: <rect>.
  WARN: Skipping align-top.svg. Contains disallowed element type: <rect>.
  WARN: Skipping circle-fill.svg. Contains disallowed element type: <circle>.
  WARN: Skipping dice-1.svg. Contains disallowed element type: <circle>.

--- Build Summary ---
Total SVG files found: 2078
- 2074 successfully processed and included
- 4 skipped (invalid size/content/no paths/error)

Path Count Distribution (for processed icons):
- 1217 icon(s) with 1 path
- 753 icon(s) with 2 paths
- 92 icon(s) with 3 paths
- 9 icon(s) with 4 paths
- 3 icon(s) with 5 paths

Output JSON written to: D:\Git\path-icons\src\bi.json
Build completed: 112.916ms

PS: простите за мой француcкий, проверявший меня на ошибки и опечатки ИИ не ругался.

Минутка занудства.

Насчет замены rect на path в align-top и align-bottom: у вас прямоугольник получается ширше (ширее?), чем в исходной картинке.

Спасибо, поправлю. Мне его ИИ перерисовывал. Надо было проверять тщательнее.

Исправленный вариант (кроме ширины у "align-top" ещё смещение вверх было):

{
  "align-bottom": [
    "M7 1h2a1 1 0 011 1v10a1 1 0 01-1 1H7a1 1 0 01-1-1V2a1 1 0 011-1z",
    "M1.5 14a.5.5 0 0 0 0 1zm13 1a.5.5 0 0 0 0-1zm-13 0h13v-1h-13z"
  ],
  "align-top": [
    "M7 3h2a1 1 0 011 1v10a1 1 0 01-1 1H7a1 1 0 01-1-1V4a1 1 0 011-1z",
    "M1.5 2a.5.5 0 0 1 0-1zm13-1a.5.5 0 0 1 0 1zm-13 0h13v1h-13z"
  ],
}

Я не очень понял зачем это все? Есть же прекрасный бесплатный пакет Avalonia.Svg который позволяет просто брать и использовать svg иконки выданные дизайнерами как есть без лишнего кода и каких то искуственных ограничений на полтора поддерживаемых тега. Костыли ради совместимости с wpf?

Ну и очень странно выглядит частичная русификация англицизмов. Solution перевели в решение (выглядит странно очень), а icons почему то айконки, не скрепно как то.

Я не очень понял зачем это все?

Ответ на ваш вопрос есть в первых двух разделах статьи. Из наиболее существенного для предлагаемого нами подхода:

  • за нас команда Bootstrap почти всё нарисовала, можно обойтись без дизайнера;

  • можно относительно легко добавить немного цвета, что-то подправить, дополнить;

  • увеличение затрат на рендеринг минимальное (штатные <Path> + <Viewbox> работают прекрасно для Avalonia и WPF);

  • альтернатива хранения ресурсов в XAML/AXAML (нет зависимости от Avalonia/WPF).

Есть же прекрасный бесплатный пакет Avalonia.Svg

This package has been deprecated.

Наверно вы имели ввиду Svg.Skia, который здесь в комментариях уже упоминали.

В любом случае: Зачем нам лишняя зависимость от внешней библиотеки в production?

Кроме того, увеличиваем углеродный след приложения (конвертация SVG в runtime - самый энергозатратный и тормозной для UI вариант).

Наверно вы имели ввиду Svg.Skia,

Да, спасибо

Ответ на ваш вопрос есть в первых двух разделах статьи. Из наиболее существенного для предлагаемого нами подхода:

Нет, ответа там нет, потому я и задал его.

за нас команда Bootstrap почти всё нарисовала, можно обойтись без дизайнера;

Это конечно прекрасно, но не отвечает на вопрос зачем изобретать велосипед который значительно менее гибкий чем существующие решения. Очевидно что библиотека для работы с svg тоже может показывать иконки Bootstrap. Ваш подход гвоздями приколочен к одному единственному набору иконок и так гладко для других уже работать не будет.

можно относительно легко добавить немного цвета, что-то подправить, дополнить

Это не преимущество. С большой долей вероятности "добавить немного цвета" без дизайнера получится довольно посредственно. Да и с точки зрения поддержки так себе подход в рантайме что то в иконках менять. Если то что показывается на экране отличается от того что лежит на диске это гарантированно рано или поздно выстрелит. Если, например, нужно несколько тем, лучше их заранее подготовить. Не говоря уже о том что это банально проще. Но даже если очень хочется то вышеупомянутая библиотека позволяет css накинуть.

увеличение затрат на рендеринг минимальное (штатные <Path> + <Viewbox> работают прекрасно для Avalonia и WPF);

По сравнению с чем? На основании чего вы делаете вывод что эта библиотека тормозить должна? Я понимаю если бы статья начиналась с "мы использовали библиотеку Х и столкнулись во с такими то проблемами производительности", а так какая то преждевременная оптимизация получается.

альтернатива хранения ресурсов в XAML/AXAML (нет зависимости от Avalonia/WPF).

Выбирать UI-фреймворк основным преимуществом которого является XAML ради того чтобы отказаться от XAML как то немного странно. Но в любом случае, svg тоже никто не заставляет в XAML запихивать, вы точно также можете загружать все в коде.

В любом случае: Зачем нам лишняя зависимость от внешней библиотеки в production?

Чтобы не тратить время на изобретение велосипеда, его отладки и погружения в него новых сотрудников, не? А зачем вам зависимость от Avalonia тогда например? Тоже же сторонняя библиотека в продакшне.

Кроме того, увеличиваем углеродный след приложения (конвертация SVG в runtime - самый энергозатратный и тормозной для UI вариант).

Это же шутка, да?

Статья имеет тип "Туториал", название начинается с "Создание контрола". Т.е., по определению, статья ориентирована на тех, кто учится или уже создает "свои велосипеды" (собственные контролы).

Я не очень понял зачем это все?

Нет, ответа там нет, потому я и задал его.

В пункте "Почему именно Bootstrap Icons?" я постарался обосновать, что не надо "изобретать велосипед" и рисовать свои иконки.
Извините, если у меня это не получилось.

Bootstrap (и позже появившийся Bootstrap Icons) являются для веб-разработчиков стандартом де-факто. Мне кажется, попробовать перетащить Bootstrap Icons из мира веб в Avalonia будет не лишним.

статья ориентирована на тех, кто учится

Учится чему? Туториал для тех кто учится выглядит примерно так:

На выходе имеем ровно то же самое что и в предлагаемом решении - иконку Bootstrap подкрашенную цветом.

Спасибо. Хороший пример для тех, кто собирается научится использовать эту библиотеку.

Но ведь название статьи "Создание контрола Avalonia/WPF для двухцветных векторных Bootstrap Icons".

<Window xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
        x:Class="Try.MainWindow"       
        Title="Try">
  <Window.Resources>
    <DrawingGroup x:Key="Geometry/DatabaseDash">
      <GeometryDrawing Brush="#dc3545" Geometry="M12.5 16a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7M11 12h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1 0-1" />
      <GeometryDrawing Brush="#7c3aed" Geometry="M12.096 6.223A5 5 0 0 0 13 5.698V7c0 .289-.213.654-.753 1.007a4.5 4.5 0 0 1 1.753.25V4c0-1.007-.875-1.755-1.904-2.223C11.022 1.289 9.573 1 8 1s-3.022.289-4.096.777C2.875 2.245 2 2.993 2 4v9c0 1.007.875 1.755 1.904 2.223C4.978 15.71 6.427 16 8 16c.536 0 1.058-.034 1.555-.097a4.5 4.5 0 0 1-.813-.927Q8.378 15 8 15c-1.464 0-2.766-.27-3.682-.687C3.356 13.875 3 13.373 3 13v-1.302c.271.202.58.378.904.525C4.978 12.71 6.427 13 8 13h.027a4.6 4.6 0 0 1 0-1H8c-1.464 0-2.766-.27-3.682-.687C3.356 10.875 3 10.373 3 10V8.698c.271.202.58.378.904.525C4.978 9.71 6.427 10 8 10q.393 0 .774-.024a4.5 4.5 0 0 1 1.102-1.132C9.298 8.944 8.666 9 8 9c-1.464 0-2.766-.27-3.682-.687C3.356 7.875 3 7.373 3 7V5.698c.271.202.58.378.904.525C4.978 6.711 6.427 7 8 7s3.022-.289 4.096-.777M3 4c0-.374.356-.875 1.318-1.313C5.234 2.271 6.536 2 8 2s2.766.27 3.682.687C12.644 3.125 13 3.627 13 4c0 .374-.356.875-1.318 1.313C10.766 5.729 9.464 6 8 6s-2.766-.27-3.682-.687C3.356 4.875 3 4.373 3 4" />
    </DrawingGroup>
    <DrawingImage x:Key="Image/DatabaseDash" Drawing="{StaticResource Geometry/DatabaseDash}"/>
  </Window.Resources>

  <Button>
    <Image Width="24" Source="{StaticResource Image/DatabaseDash}" />
  </Button>
</Window>

Попробуйте такой вариант (конвертация SVG в XAML). Мне кажется у него есть некоторые преимущества. Для простоты здесь "DrawingImage" помещен в локальные ресурсы, но на практике их принято держать в отдельном файле, например, "Resources/Icons.axaml".

ПыСы Извините, немного вопрос не по окладу: а почему "айконка", а не "иконка"?

Чего придираетесь? Еду как могу...

ПыСы: Обновил текст статьи, сделал замену: "айкон" -> "икон".

А почему вы ограничились только двумя цветами, хотя часть иконок в этом наборе (более сотни) содержит больше двух частей (три и более элемента path)?

На всякий случай: я не докапываюсь, просто меня зантересовал сам набор иконок, который вы предложили и методика их использования для нужд народного хозяйства.

Спасибо, правильный вопрос. Я даже это объяснял в статье, но потом вырезал (и так объемно получилось).

Основной мотив: не хотелось просаживать рендеринг (на сотнях элементов становится заметно). Кроме того, из личного опыта - редко требовалось более 2-х цветов (для иконок в меню, тулбале, сайдбаре, гриде). Речь не идет о многоцветных логотипах, для этого можно использовать, например, сложную геометрию в XAML-ресурсе.

Обычно один цвет нужен для привлечения внимания (красный, желтый) и повышения узнаваемости (брэнд-колор).

Второй цвет полезен, чтобы меньше промахивались: по иконкам 16x16 можно не отличить команды "Удалить запись" от "Добавить запись" (наличие красного дает больше шансов).

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации