Pixi.js: Реальная поддержка SVG

Созданный на 29 июн. 2017  ·  30Комментарии  ·  Источник: pixijs/pixi.js

Для Pixi было бы здорово иметь возможность создавать графическое представление SVG в виде иерархии (а не просто загружать текстуру, как сейчас).

@psyrendust ^ Эй, можешь ли ты

Stale 🙏 Feature Request

Самый полезный комментарий

Я думаю, что это то, что вы хотите, используя webpack.
https://github.com/blunt1337/pixi-svg-loader

Все 30 Комментарий

Возможно, вы захотите проверить эту библиотеку, которую я сделал:
https://github.com/bigtimebuddy/pixi-svg
https://bigtimebuddy.github.io/pixi-svg/example/

Из-за ограничений рисования в Pixi поддерживаются не все функции svg.

@trusktr не могли бы вы дать пример использования? Вы имеете в виду, что группы как контейнеры, а наборы примитивов - как спрайты?

Потому что это то, о чем я думал. Можно было бы создать атлас текстур и использовать переводы и повороты из SVG для создания иерархии спрайтов.

Одна проблема, которую я вижу в этом подходе, - это привязки (на случай, если мы хотим что-то оживить). Например, Inkscape добавляет якоря в качестве настраиваемых атрибутов, но их нет в стандартном afaik. Пример того, что я имею в виду:

2017-07-01 08_56_56-_new document 1 - inkscape

Якорь этой группы из трех путей (вверху слева от синего прямоугольника) определяется как inkscape:transform-center-x и inkscape:transform-center-y .

    <g
       id="g4512"
       inkscape:transform-center-x="-65.892627"
       inkscape:transform-center-y="43.567609"
       transform="rotate(-5.9407468,27.740957,88.735118)">
      <path
         inkscape:connector-curvature="0"
         id="rect4485"
         d="m 24.502618,78.898505 h 50.619309 c 3.986749,0 7.196297,3.209548 7.196297,7.196296 v 70.274069 c 0,3.98675 -3.209548,7.1963 -7.196297,7.1963 H 24.502618 c -3.986748,0 -7.196296,-3.20955 -7.196296,-7.1963 V 86.094801 c 0,-3.986748 3.209548,-7.196296 7.196296,-7.196296 z"
         style="opacity:1;fill:#005e92;fill-opacity:1;stroke:none;stroke-width:0.1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers fill stroke" />
      <path
         inkscape:connector-curvature="0"
         id="rect4485-4"
         d="m 66.160572,123.8869 h 50.619318 c 3.98675,0 7.1963,3.20955 7.1963,7.1963 v 70.27406 c 0,3.98675 -3.20955,7.19631 -7.1963,7.19631 H 66.160572 c -3.986734,0 -7.196284,-3.20956 -7.196284,-7.19631 V 131.0832 c 0,-3.98675 3.20955,-7.1963 7.196284,-7.1963 z"
         style="opacity:1;fill:#920000;fill-opacity:1;stroke:none;stroke-width:0.1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers fill stroke" />
      <path
         inkscape:connector-curvature="0"
         id="rect4485-3"
         d="m 106.60403,73.994048 h 50.61931 c 3.98675,0 7.1963,3.209548 7.1963,7.196296 v 70.274066 c 0,3.98675 -3.20955,7.19631 -7.1963,7.19631 h -50.61931 c -3.98675,0 -7.196288,-3.20956 -7.196288,-7.19631 V 81.190344 c 0,-3.986748 3.209538,-7.196296 7.196288,-7.196296 z"
         style="opacity:1;fill:#009228;fill-opacity:1;stroke:none;stroke-width:0.1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers fill stroke" />
    </g>

Хотя я ценю ваши усилия @bigtimebuddy, я не думаю, что рендеринг примитивов SVG в pixi - хорошая идея.

Также проверьте это:
https://css-tricks.com/rendering-svg-paths-in-webgl/

Я думаю, что это то, что вы хотите, используя webpack.
https://github.com/blunt1337/pixi-svg-loader

@OSUblake круто, похоже, он действительно делает то, что я имел в виду. Надо попробовать. 👍

@bigtimebuddy Спасибо! Я открыл там новый выпуск. Было бы здорово иметь полный граф сцены Pixi.

@RanzQ

@trusktr не могли бы вы дать пример использования? Вы имеете в виду, что группы как контейнеры, а наборы примитивов - как спрайты?

Да, но примитивы были бы объектами Graphics а не спрайтами.

Одна проблема, которую я вижу в этом подходе, - это привязки (на случай, если мы хотим что-то оживить). Например, Inkscape добавляет якоря в качестве настраиваемых атрибутов, но их нет в стандартном afaik. Пример того, что я имею в виду:

Я не против не поддерживать нестандартные вещи, я могу жить только со стандартизованными API. Легко мог бы быть плагин для поддержки специфичных для inkscape вещей.

Хотя я ценю ваши усилия @bigtimebuddy, я не думаю, что рендеринг примитивов SVG в pixi - хорошая идея.

Почему ты так думаешь?

@OSUblake

Я думаю, что это то, что вы хотите, используя webpack.
https://github.com/blunt1337/pixi-svg-loader

Это довольно круто, за исключением того, что ограничивается Webpack, а также ограничивается средами с инструментами, не работает на клиенте. Я ищу API, который можно использовать с Pixi.js во время выполнения (а не во время сборки).


Что я хочу (я думаю, но я не самый опытный пользователь Pixi.js, поэтому советую, если что-то еще лучше, например, использование спрайтов), это иметь граф сцены DisplayObject, который имеет ту же структуру, что и SVG DOM, используемый для генерации дерево Pixi от. Это, на мой взгляд, мощное средство для манипуляции и анимации, без необходимости повторного рендеринга всего SVG в каждом кадре только для анимации одного примитива (из возможных сотен или тысяч).

То , что я думаю , что я буду делать, если что - то с открытым исходным кодом еще не существует, это взять @bigtimebuddy «ы Pixi-SVG или @saschagehlich» s Pixi-SVG-графики , а также изменять их (или использовать аналогичные понятия) , чтобы создать Pixi Graphics tree отражает дерево SVG, а не просто рисует на одном объекте Graphics .

@trusktr Я понимаю, что для анимации на основе примитивов может быть полезно создавать объекты Graphics вместо Sprites . Но я думаю, что решение может поддерживать как Graphics для простых SVG, так и Sprites для более сложных.

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

Это будет проблемой для художника, так как нужно знать, какие функции можно использовать, а какие нет. У нас уже есть хороший рендерер SVG - браузер. Но если SVG содержит простые примитивы без эффектов, то, вероятно, его можно проанализировать как объекты Graphics .

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

Создавать текстуры из SVG довольно просто, используя Canvas 2d и

var path = new Path2D("M10 10 h 80 v 80 h -80 Z");
context.fill(path);

Демонстрация морфинга пути
https://codepen.io/osublake/pen/oWzVvb

Я собирался работать над улучшенным полифилом, так как у того, что было у Google, возникли проблемы с анализом сложных путей SVG.
https://github.com/google/canvas-5-polyfill

@RanzQ

У нас уже есть хороший рендерер SVG - браузер.

Но это так медленно-у-у-у. Он отображается в графическом процессоре или процессоре? На мой взгляд, производительность, которую я испытываю, не идет ни в какое сравнение со скоростью, например, аналогичных вещей, нарисованных с помощью Pixi.js. Мне кажется, что собственный движок SVG делает слишком много работы.

Даже Canvas 2d работает медленнее по сравнению с WebGL. Сравните здесь разницу между WebGL и Canvas: http://pixijs.github.io/pixi-particles-editor/ (прокрутите вниз, чтобы переключаться между WebGL и отрисовкой Canvas). Canvas заметно медленнее.

Я просто хочу нарисовать SVG и сделать это как можно быстрее. Пока, по крайней мере, концептуально, кажется, что рисование SVG с помощью WebGL API, такого как Pixi.js или Two.js, является самым быстрым способом. Единственным недостатком на данный момент является то, что не все функции SVG поддерживаются полностью.

@OSUblake

Создавать текстуры из SVG довольно просто, используя Canvas 2d и Path2D api.

Canvas 2D по-прежнему заметно медленнее, чем WebGL, посмотрите эту демонстрацию, я только что связал два абзаца вверх.

Демонстрация морфинга пути
https://codepen.io/osublake/pen/oWzVvb

Классная демка! В этом случае вы анимируете простой путь в PathProxy. Вероятно, этого достаточно для конкретного случая использования. Но представьте, что вы рисуете в SVG кучу объектов, например 100 узлов, и анимируете их все, а затем хотите, чтобы все это было текстурой, обернутой вокруг сферы.

Или представьте, что частицы в этой демонстрации выполняются с помощью SVG и анимации узлов SVG DOM, затем выполняется рендеринг в виде текстуры с drawImage на холсте и, наконец, помещается в квадратик 3D-приложения webgl. Это было бы слишком медленно!

Ваша демонстрация выполняется быстро, потому что анимация частиц находится в WebGL через Pixi.

Если бы рендеринг SVG с помощью Pixi был поддерживаемой функцией и была создана иерархия, отражающая иерархию SVG, то можно было бы сопоставить изменения с элементом display:none <svg> ( display:none так что, надеюсь, это мешает движку SVG браузера работать, потому что ничего не нужно рендерить) в изменения в дереве Pixi.js.

Я думаю, что это был бы самый быстрый способ рисовать SVG, потому что Pixi быстрее, предоставляя удобство DOM, которым можно манипулировать с помощью React, Angular и т. Д. Я хочу иметь дерево SVG DOM, которым я могу манипулировать, кто рендеринг будет быть быстрее, чем медленный движок SVG браузера. Может, я слишком многого прошу. Кажется, что с сегодняшними технологиями рендеринг SVG слишком медленный по общепринятым стандартам (нам нужны скорости игрового движка).

@trusktr

Но это так медленно-у-у-у.

Под этим я имел в виду, что мы можем рисовать текстуры SVG с помощью браузера, он медленный, но поддерживает все функции. Конечно, вы бы не стали делать такую ​​анимацию. Вы можете создать атлас текстур и потом анимировать спрайты. Например, если вы хотите создать двухмерных спинномозговых персонажей, это будет подходящим вариантом.

Думаю, это пример того, что вам нужно: https://github.com/bodymovin/bodymovin/issues/184

Задача непростая, и эта анимация, например, достаточно сложна, чтобы играть медленно на моем старом Android-телефоне, который отлично воспроизводит сцены Pixi на основе спрайтов. Я не вижу разницы в версии SVG и Pixi. Хотя может быть просто проблема с оптимизацией.

Также проверьте это: https://www.gatherdigital.co.uk/community/post/high-performance-webgl/78

Так что, на мой взгляд, в SVG есть две разные потребности. Один с меньшим количеством функций SVG, разделенный на примитивы, другой с атласом, отображаемым браузером, например, спрайтами, являющимися узлами <g> .

Другой подход может заключаться в поиске лучшего совместимого формата или инструментов для векторной графики, чем SVG. Если вам нужно что-то масштабируемое, SVG имеет свои ограничения в PixiJS по причинам, уже сформулированным @RanzQ . Существует так много функций, которые не поддерживаются в возможностях рисования Pixi, доступных в SVG, что любой простой перевод рисунка будет второсортным.

Еще один подход, который я бы порекомендовал, - это PixiAnimate (https://github.com/jiborobot/pixi-animate-extension), это собственное расширение (отказ от ответственности, я его автор) для Adobe Animate, которое хорошо экспортирует точную графику. Кроме того, вы можете создать любую иерархию, которую хотите, используя вложенные символы и слои или анимировать.

@bigtimebuddy Существует ли рабочий процесс для создания атласов текстур из векторной графики с помощью Animate? Я искал такой рабочий процесс, где можно было бы создать сцену Pixi с помощью пользовательского интерфейса.

Кажется возможным создавать атласы в свежем выпуске Animate, но пробовали ли вы для этого свое расширение: http://blogs.adobe.com/contentcorner/2017/07/03/create-a-texture-atlas-with -animate-cc-for-your-favour-game-engine /

@RanzQ , да PixiAnimate может экспортировать отдельные изображения или таблицы спрайтов в формате атласов TexturePackers. Однако векторные формы не преобразуются в текстуры автоматически. Для этого в Animate необходимо использовать «Преобразовать в растровое изображение».

@trusktr

Ваша демонстрация выполняется быстро, потому что анимация частиц находится в WebGL через Pixi.

Точно. Я не предлагал использовать холст в качестве основного средства визуализации. Только для создания текстур / спрайтов при изменении геометрии. Это должно быть достаточно быстро для большинства случаев использования. Я думаю, что именно так Two.js выполняет рендеринг путей в WebGL.

А использование объектов Path2D может улучшить производительность холста, поскольку браузер будет кэшировать векторы для пути. Это позволяет использовать один и тот же объект пути более одного раза, даже с разными контекстами и разрешениями холста.

@OSUblake

Точно. Я не предлагал использовать холст в качестве основного средства визуализации. Только для создания текстур / спрайтов при изменении геометрии. Это должно быть достаточно быстро для большинства случаев использования. Я думаю, что именно так Two.js выполняет рендеринг путей в WebGL.

Да, это звучит как хороший подход. Например, если в элементе <circle> изменяются только атрибуты cx и cy , это означает, что оптимизацией будет преобразование существующей сетки или спрайта без создания новенький.

Вот сравнение Pixi, Two и нативного SVG:

Почему Pixi заметно медленнее? Причина в том, что он пересчитывает (пересчитывает или повторно растеризует) на основе команд рисования в каждом кадре?

В Two.js Circle - это объект со свойствами x, y и radius. С этим API очевидно, что круг не нужно повторно оценивать / повторно растеризовывать, если изменяются только x и y.

Не так очевидно, как эта оптимизация будет сделана с помощью стиля команды рисования Pixi.

@trusktr

Почему Pixi заметно медленнее? Причина в том, что он пересчитывает (пересчитывает или повторно растеризует) на основе команд рисования в каждом кадре?

Нет. Он просто создает множество треугольников, что убивает производительность графического процессора. Вы можете увидеть разницу, если нарисуете прямоугольник без стиля линии. Он будет отображать его как спрайт, поэтому производительность будет намного лучше. 10000 рт.
https://codepen.io/osublake/pen/PjrbWq/

Вы изучали возможность использования полей расстояний для растеризации? Я знаю, что со шрифтами он хорошо работает, если не увеличивать слишком сильно. Мне интересно, можно ли его использовать для анимации данных пути.
https://github.com/Tw1ddle/WebGL-Distance-Fields/tree/master/sdf

https://www.shadertoy.com/view/ltXSDB

Мои предыдущие примеры были совершенно неточными, потому что я не понимал, что JSBin рано выходит из циклов for , поэтому на моем Macbook Pro он отображал только 500 кругов (даже если я установил n на 10000 ). Я обновил примеры, поэтому все они отображают 2000 кругов без прерывания цикла JSBin:

Пример SVG по-прежнему самый медленный при анимации только положения круга (не радиуса).

Вот Two.js и SVG, также анимирующие радиусы:

Я не включил версию Pixi.js, потому что не знал, как изменить версию без анимации радиуса. Как бы вы обновили версию анимации без радиуса с помощью Pixi.js, чтобы включить анимацию радиуса?

Как бы вы обновили версию анимации без радиуса с помощью Pixi.js, чтобы включить анимацию радиуса?

Производительность может действительно начать падать здесь. Вы должны очистить графический объект, что сбрасывает все.
https://codepen.io/osublake/pen/8217810e590672c5a5327596e33c4b1a?editors=0010

Теперь посмотрим на эту демонстрацию с использованием холста 2d для создания текстур. 3000 кругов на моей машине со скоростью 60 кадров в секунду.
https://codepen.io/osublake/full/MoMeMg/

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

@OSUblake Упс, я ответил на последний вопрос, прежде чем увидел ваш новый ответ.

Производительность может действительно начать падать здесь. Вы должны очистить графический объект, что сбрасывает все.
https://codepen.io/osublake/pen/8217810e590672c5a5327596e33c4b1a?editors=0010

Это то, чего я боялся, что не идеально. Он начинает приближаться к собственной медлительности SVG.

Теперь посмотрим на эту демонстрацию с использованием холста 2d для создания текстур. 3000 кругов на моей машине со скоростью 60 кадров в секунду.
https://codepen.io/osublake/full/MoMeMg/

Святое дерьмо, вау! Хорошо! Итак, поехали, на данный момент это лучший способ сделать это (и даже с 3000 <canvas> )!

Почему это намного быстрее? Может быть, разработчики нативного SVG могут извлечь уроки из этого (а также Pixi.js и Two.js)?

Может быть, использование этого подхода в Pixi.js потребует изменений в столкновении / выборе? Вместо сетки будет прямоугольная текстура.

@trusktr Причина в том, что вы рисуете на холсте один раз, а затем загружаете его как текстуру в графический процессор. В этом примере для каждого радиуса создается отдельная текстура, округленная до 4 пикселей (если я правильно понял 😄). Анимация достаточно быстрая, поэтому вы не увидите смену текстуры.

Вы можете делать то же самое с API рисования Pixi, кэшируя графические объекты ( cacheAsBitmap ). Таким образом, вы можете нарисовать примитивы один раз и быстро перерисовать их из кеша.

В этом примере для каждого радиуса сгенерирована отдельная текстура с шагом 4 пикселя (если я правильно понял 😄)

Фактически это округление до 0,25 шага. Какую субпиксельную точность вы действительно можете увидеть?

Если это забавно, то посмотрите, как работает Pixi CanvasTinter. Или как работает анимация листа спрайтов. Вы жертвуете некоторой памятью в обмен на производительность, и при хорошей стратегии кэширования она может работать.

Вы можете делать то же самое с API рисования Pixi, кэшируя объекты Graphics (cacheAsBitmap). Таким образом, вы можете нарисовать примитивы один раз и быстро перерисовать их из кеша.

Использование cacheAsBitmap может выглядеть не очень хорошо, потому что графика будет иметь алиасинг. Чтобы получить сглаженную графику, вам нужно использовать generateCanvasTexture. Так или иначе, у вас будет холст, но с помощью API графики Pixi вы не сможете делать простые вещи, например, изменять штриховую линию штриха.

Вы можете делать то же самое с API рисования Pixi, кэшируя объекты Graphics (cacheAsBitmap).

Чтобы получить сглаженную графику, вам нужно использовать generateCanvasTexture

Могу ли я с помощью любого из этих двух вариантов анимировать радиус, как в вашем примере @OSUblake ?

(кстати, спасибо, ребята, открываю глаза на приемы рендеринга, о которых я раньше не догадывался).

@trusktr Да, вам просто нужно создать много объектов Graphics с разным радиусом и создать карту сгенерированных текстур (чтобы затем вы могли использовать кешированную текстуру для каждого радиуса). С cacheAsBitmap вы будете отображать объекты Graphics вместо текстур, но у вас не будет сглаживания, как сказал @OSUblake .

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

Но я согласен, у Canvas лучший API для рисования, поэтому я бы его использовал. А для SVG иерархию можно разделить на атлас, как это делает pixi-svg-loader (я думаю?). Или, если вы хотите, чтобы лист спрайтов был похож на анимацию, это тоже можно сделать, отрисовав состояния анимации на холсте.

Может быть, использование этого подхода в Pixi.js потребует изменений в столкновении / выборе? Вместо сетки будет прямоугольная текстура.

Хотя холст и не так быстр, как многоугольник, у него есть метод проверки попадания на пути - isPointInPath . Посмотрите, как это работает на этой карте.
https://codepen.io/osublake/pen/dzYzab/?editors=0010

Кажется, в three.js есть svgloader, возможно, что-то, что можно сопоставить с pixi.js
https://github.com/mrdoob/three.js/blob/master/examples/js/loaders/SVGLoader.js

Эта проблема была автоматически помечена как устаревшая, поскольку в последнее время не было активности. Он будет закрыт, если больше не будет активности. Спасибо за ваш вклад.

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

Была ли эта страница полезной?
0 / 5 - 0 рейтинги