Векторизация, небольшой баг и семистильный костыль

    Только что я нашёл решение странного бага, который преследовал меня целую неделю. Эта небольшая эпопея произвела на меня такое впечатление, что я решил поделиться ею с сообществом. Ошибка, которую я обнаружил, возможно, присутствует лишь в моей прошивке и, скорее всего, никогда вас не затронет. Разве что вы решите делать Cordova/PhoneGap/HTML5 приложение с векторной графикой для Windows Phone 8.1

    Интерлюдия


    Почти четыре года назад Microsoft призвал разработчиков делать мобильные приложение под Windows на HTML5 и PhoneGap в частности.
    Когда мне понадобилось попробовать себя в чём-то новом, мне вспомнился этот призыв…

    «В новом так в новом», — решил я и начал переписывать своё старое приложение на JS. Так как Cordova (а значит и PhoneGap) поддерживают iOS и Android, где в последнее время разрешения экранов перешагнули планку в 4K, я решил перевести всю графику из приложения (а это почти весь контент) в вектор. Ведь нужно думать о будущем и после Microsoft Store попытаться вернуться в Google Play.

    Интересная заметка

    Если иллюстратор, который взялся векторизовать ваш контент в SVG, пишет, что может в вектор — возможно, он использует SAI и вам не подходит.

    Нет смысла писать, каково программировать и верстать под IE. Я лишь замечу, что IE в WebView не всегда ведёт себя, как обычный мобильный IE, а тот себя ведёт не всегда, как Standalone IE 9 на котором рекомендуют тестировать контент. Бывалые разработчики подумают, что я столкнулся с очень интересным поведением браузера из-за стартового тега XML или же хочу пожаловаться на отсутствие нативной поддержки svg в WP, но это не так; можете пока отвести курсоры от кнопки, уменьшающей мою карму.

    Интересная заметка

    Если иллюстратор, который взялся векторизовать ваш контент после предоплаты, опубликовал в ВК своё фото с кальяном — скорее всего, контент будет готов не скоро.

    Немного о векторизации


    До того, как я решил векторизовать контент, мне казалось, что вектор — только для иконок, и векторная графика высокого качества где-то в далёком будущем. Оказалось, что есть множество программ для автоматической векторизации. Благодаря алгоритмам Vector Magic может достойно векторизовать даже фото! Это казалось мне магией, но чуть и не подвело. Программно векторизованные картинки весили просто неприлично много и их отображение просто вешало смартфон. Я чуть было не отказался от вектора, но мне хватило ума попробовать использовать графику, созданную вручную.

    VectorMagic Ручная векторизация Оригинал (сжат с потерями)
    >1.4mb 75kb 74.1kb

    Комментарии излишни.

    Интересная заметка

    Если иллюстратор, который взялся векторизовать вашу простенькую картинку, присылает вам SVG в несколько мегабайт, вам стоит проверить наличие встроенных в SVG png файлов (тег image) или подозревать его в автоматической векторизации.

    К моему сожалению полностью уйти от растровой графики не получилось. Её пришлось использовать для создания эффекта размытия. (svg позволяет интегрировать в себя png) Тем не менее, мне удалось сильно выиграть весе приложения
    Android + PNG (сжат с потерями) PhoneGap + SVG (ручная векторизация)
    ~24mb ~7mb

    Это обусловлено большим количеством чёрно-белой графики, состоящей из геометрических фигур. Хотя, конечно, от некоторых графических эффектов пришлось полностью отказаться из-за трудозатрат на их реализацию в векторе.

    Собственно баг


    После работы иллюстратора у меня оказалось на руках несколько многослойных AI файлов. Каждый слой представлял собой изменённый предыдущий слой. (что-то такое)
    Приложение подразумевает много SVG, где каждый SVG это отдельный слой из AI. У меня получилась интересная ситуация:
    • Если я отображал SVG любого верхнего слоя, всё отображалось адекватно.
    • Если я отображал SVG другого слоя, в PhoneGap на WP 8.1 стабильно ничего не отображалось. (на самом деле периодически баг проявлялся в Android PhoneGap со старым WebView)

    Первым делом, я попробовал сохранить «проблемные» слои в разных конфигурациях. Но это никак не помогало: изображения всё так-же не отображались. Тогда я решил покопаться в текстовом представлении SVG файлов и менять их вручную, пытаясь найти закономерности.

    Очевидная заметка

    Редактировать оптимизированные SVG файлы в текстовом виде — плохая идея.

    И вот что я обнаружил:
    • Если к НЕверхнему слою добавить стили ВЕРХНЕГО слоя, то картинка начнёт отображаться.

    Это выглядело примерно так:
    Верхний слой в виде SVG файла (отображается)
    <svg id="lesson_2_7" data-name="lesson 2 7" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 686 526"><defs><style>.cls-1{fill:#fff;}.cls-2{fill:#a2a2a2;}.cls-3{fill:#6c6c6c;}.cls-4{fill:#a9aeb7;}.cls-5{fill:#6f6f6f;}.cls-6{mask:url(#mask);}.cls-7{fill:#adadad;}.cls-8{mask:url(#mask-2);}.cls-9{fill:#46cc00;}.cls-10{fill:#fff7f7;}.cls-11{filter:url(#luminosity-noclip-2);}.cls-12{filter:url(#luminosity-noclip);}</style> ...
    


    Не верхний слой в виде SVG файла (не отображается)
    <svg id="lesson_2_5" data-name="lesson 2 5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 686 526"><defs><style>.cls-1{fill:#fff;}.cls-2{fill:#fff7f7;}</style> ...
    


    Не верхний слой в виде SVG файла + style от верхнего слоя (отображается)
    <svg id="lesson_2_5" data-name="lesson 2 5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 686 526"><defs><style>.cls-1{fill:#fff;}.cls-2{fill:#a2a2a2;}.cls-3{fill:#6c6c6c;}.cls-4{fill:#a9aeb7;}.cls-5{fill:#6f6f6f;}.cls-6{mask:url(#mask);}.cls-7{fill:#adadad;}.cls-8{mask:url(#mask-2);}.cls-9{fill:#46cc00;}.cls-10{fill:#fff7f7;}.cls-11{filter:url(#luminosity-noclip-2);}.cls-12{filter:url(#luminosity-noclip);}</style> ...
    


    Посчитав, что оптимизатор SVG удаляет некоторые стили в нижних слоях, я начал искать отсутствующие стили в «проблемных» файлах. Их не было; кроме того, меня смущал файл у которого не отображался ни один из слоёв, но тогда я отнёс это к ошибкам совместимости.

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

    • Добавился ai файл у которого не отображался ни один из слоёв
    • Добавился ai файл у которого слои отображались начиная с 5 (из 7)

    Вспомнив все свои знания с пар по Тестированию ПО и игре в Jenga, я начал поштучно удалять стили, пытаясь обнаружить зарытую собаку. После аннигиляции стиля cls-7 картинка переставала отображаться в приложении. Конечно, я вернул cls-7 и удалил cls-6: картинка пропала. Попробовал заменить cls-7 на копию cls-6: картинка отобразилась. Заменил все стили кроме cls-1 и cls-2 на множество пустышек cls-0{fill:#fff;}: картинка отобразилась.

    Это заняло у меня неделю. В PhoneGap приложении для Windows Phone 8.10.14234.375 (Lumia 435 DS) не отображаются SVG изображения у которых меньше семи стилей. В итоге, или иллюстратор должен добавлять невидимые разноцветные точки, или я должен написать скрипт, который будет анализировать файл и добавлять в него «пустые» стили при необходимости. Конец.

    P.S. Для полной уверенности я попросил иллюстратора нарисовать каракулю (2 стиля).
    Она не отобразилась. Наверное, слишком скучная…

    Интересная заметка

    Если иллюстратор день за днём пересохраняет один и тот же файл, это хороший иллюстратор. Спасибо за понимание, Василиса.
    • +15
    • 7,5k
    • 8
    Поделиться публикацией
    Похожие публикации
    Реклама помогает поддерживать и развивать наши сервисы

    Подробнее
    Реклама
    Комментарии 8
    • +1
      Не решение бага, но небольшое облегчение жизни — не пробовал использовать внешние стили css, в svg указывая только ссылку? Так понимаю он в ai файле каждый svg видит изолированно, поэтому и не видит иерархии и других стилей.
      www.w3.org/TR/SVG2/styling.html
      • 0
        Внешние не пробовал. Мне тогда придётся очень часто их отключать/подключать.
        Кроме того, я пробовал атрибуты представления или что-то такое. Это когда стиль напрямую описывается в линии. Не помогло.
      • 0
        Я не до конца понял суть бага, но что-то подобное я встречал при отображении множества svg на странице. Проблема заключалась в том, что при экспорте некоторые айдишники или классы внутри svg совпадают с другими. Это могут быть стили или clip path, и все это так или иначе сказывается на отображении svg. На одном из проектов у меня была подобная проблема, когда отображение всех svg превращало общую картинку в непотребство. Решил я все это крайне просто — взял SVGO, модифицировал один из встроенных плагинов в свой и моя проблема на том была решена(только нужно прогонять все svg пакетно в пределах одного процесса ноды, чтобы айдишники были уникальными для любого из файлов; сделать это можно, например, через любой из плагинов к gulp).
        И еще, встраивание стилей, если это не оправдано чем-то разумным лучше избегать по моему опыту и делать все стили инлайновыми для объектов, при экспорте из люстры это можно так же указывать.
        • 0
          Суть бага в том, что в Фонгепе под ВинФон картинка не отображалась, если там было меньше семи разных стилей (цветов)
          Дело не в пересечении стилей. Я проверял картинки по одной. Кстати даже при множестве svg всё было нормально.
          • +1
            А если не использовать CSS, а обходиться только свойствами svg, то что происходит с картинкой?
            • 0
              Ну в SVG насколько я понимаю без CSS никуда. Ведь через стили задаются цвета линий.
              Тег
              <style> 
              
              прямо в SVG файле. Я про это.
              • +2
                Ну, и да и нет.
                Вот простой пример:
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 33.069 54.544">
                    <path fill="none" stroke="#033144" stroke-width="3" stroke-miterlimit="10" d="M16.535 19.213l.362 35.315" />
                    <path d="M16.897 54.528S15.735 32.18 33.07 28.618c0 .002-2.085 25.885-16.173 25.91z" fill="#033144" />
                    <path d="M16.172 54.528S17.334 32.18 0 28.618c0 .002 2.084 25.885 16.172 25.91z" fill="#033144" />
                    <path d="M24.996 2.488L19.71 8.62 16.535 0 13.36 8.62 8.074 2.488a19.814 19.814 0 0 0-.76 5.49c0 7.64 4.13 13.83 9.22 13.83 5.093 0 9.22-6.19 9.22-13.83 0-1.95-.27-3.806-.758-5.49z" fill="#e1722f" />
                </svg>
                

                С одной стороны, fill мы можем и в <style/> прописать, а можем и как свойство объекта использовать.
                Потому и спрашивал: присутствует ли проблема при использовании только инлайн-свойств, без <style/>?
                • +2
                  Я понял вас.У меня просто некоторая проблема с терминами. Да конечно я пробовал так сохранять. Проблема присутствовала.

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.