Особенности работы в Safari

Safari historically демонстрирует ряд специфических особенностей при работе с SVG-анимациями, особенно когда используется подход на основе манипуляции свойствами stroke-dasharray и stroke-dashoffset, на котором строится библиотека Vivus. Эти особенности проявляются как на уровне движка рендеринга, так и на уровне JavaScript-реализации DOM и графического пайплайна.

Одной из ключевых операций Vivus является получение длины пути через getTotalLength(). В Safari этот метод может вести себя менее стабильно при сложных путях.

Особенности:

  • При наличии самопересечений или комбинированных кривых Safari может возвращать значения с заметными округлениями.
  • В некоторых версиях наблюдается задержка вычисления длины пути до момента полной отрисовки SVG в DOM.
  • При динамической вставке SVG через innerHTML результат getTotalLength() может быть равен 0 до следующего кадра.

Практический эффект — анимация Vivus может стартовать с «обнулённой» геометрией или с резким скачком первого кадра.

Решение на уровне интеграции заключается в отложенном инициализации после первого requestAnimationFrame:

requestAnimationFrame(() => {
  new Vivus('svg-id', { duration: 200 });
});

Особенности stroke-dasharray в Safari

Safari использует собственный путь рендеринга SVG, который отличается от Blink и Gecko в обработке дробных значений stroke.

Ключевые различия:

  • округление dash-значений происходит раньше, чем в Chrome
  • при малых сегментах пути возможны визуальные разрывы
  • при масштабировании SVG через CSS transform возможны артефакты заполнения

Vivus, основанный на точной сегментации пути, может демонстрировать:

  • «дрожание» линии при анимации
  • неравномерное появление сегментов
  • визуальные разрывы на кривых Безье

Особенно заметно при использовании type: 'delayed' или type: 'oneByOne', где каждый сегмент рассчитывается отдельно.


GPU-ускорение и compositing layers

Safari по-другому управляет композитными слоями для SVG по сравнению с Chromium.

Особенности:

  • SVG не всегда автоматически переводится в GPU-layer
  • применение transform: translateZ(0) не гарантирует ускорение SVG-узлов
  • при большом количестве path-элементов происходит fallback на CPU-рендеринг

В Vivus-анимациях с большим количеством линий это приводит к:

  • просадкам FPS при анимации отрисовки
  • увеличению времени первого кадра (first paint delay)
  • заметной нагрузке на main thread

Часто применяют принудительную изоляцию слоя:

svg {
  will-change: transform;
  transform: translate3d(0, 0, 0);
}

Однако Safari может игнорировать will-change для SVG, поэтому эффект нестабилен.


requestAnimationFrame и тайминги

Safari, особенно на iOS, имеет особенности планирования кадров.

Наблюдается:

  • более агрессивное троттлинг-ограничение в фоне
  • изменение частоты вызова requestAnimationFrame при низком battery mode
  • задержки первого кадра при сложных SVG-деревьях

Vivus, рассчитывающий прогресс анимации по времени, может демонстрировать:

  • неравномерную скорость прорисовки
  • «залипания» анимации при переключении вкладок
  • резкое ускорение после возврата на вкладку

При использовании временных функций Vivus (start, progress) важно учитывать, что Safari может возвращать скачкообразные deltatime значения.


Inline SVG против внешних файлов

Safari имеет различия в обработке inline SVG и SVG, загруженных через <img> или <object>.

Vivus работает только с inline SVG, но даже в этом случае:

  • DOM-инициализация может быть отложенной
  • стили CSS могут применяться после первого рендера
  • SMIL-атрибуты (если присутствуют) могут конфликтовать с JS-анимацией

Особенность Safari заключается в более позднем применении computed styles к SVG-элементам, что влияет на начальные значения stroke.


Масштабирование и viewBox

Safari по-другому интерпретирует subpixel rendering внутри SVG при изменении viewBox.

Проблемы:

  • дрожание линий при анимации на 100% ширины контейнера
  • изменение толщины stroke при масштабировании
  • различие в антиалиасинге на Retina-дисплеях

Vivus-анимации, зависящие от точной геометрии пути, могут выглядеть «плавающими».

Часто помогает фиксация shape-rendering:

svg path {
  shape-rendering: geometricPrecision;
}

Однако Safari может игнорировать или частично применять это свойство.


Особенности обработки stroke-linecap и stroke-linejoin

Safari имеет отличия в рендеринге соединений линий:

  • round cap может визуально увеличивать длину пути
  • miter join может давать неожиданные острые артефакты
  • при анимации dash-offset наблюдаются микросдвиги на стыках

Vivus, который визуально «раскрывает» путь, может демонстрировать:

  • небольшие «переломы» на соединениях сегментов
  • разницу между началом и концом анимации одного и того же path

Эффект усиливается на сложных логотипах и иконках с тонкими линиями.


Проблемы с пересчётом layout при анимации

Safari чувствителен к частым обращениям к layout API:

  • getBoundingClientRect
  • offsetWidth
  • clientHeight

Vivus в некоторых режимах может триггерить повторные расчёты геометрии при каждом шаге анимации, если SVG вложен в сложный DOM.

Это приводит к:

  • layout thrashing
  • падению производительности при большом количестве path
  • блокировке UI-thread

Особенно заметно при одновременной анимации нескольких SVG.

Оптимизация заключается в изоляции SVG в отдельный слой DOM без частых измерений.


Ограничения iOS Safari

Mobile Safari накладывает дополнительные ограничения:

  • ограничение CPU при сворачивании вкладки
  • заморозка requestAnimationFrame в background
  • ограничение памяти для SVG DOM-структур

Vivus-анимации на сложных иллюстрациях могут:

  • останавливаться при скролле
  • «догонять» прогресс после восстановления активности
  • сбрасывать прогресс при low memory warning

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


Маски и clipPath в Safari

Vivus иногда используется вместе с clipPath или mask для усиления эффекта рисования.

Safari имеет особенности:

  • clipPath с transform может рендериться с задержкой
  • mask на SVG иногда обновляется только после repaint
  • комбинация stroke-dashoffset + mask вызывает визуальные артефакты

На сложных сценах возможен эффект «двойного прорисовывания», когда часть пути уже видна вне синхронизации с маской.


Поведение при изменении размеров контейнера

Safari пересчитывает SVG viewBox при ресайзе с задержкой.

В результате:

  • анимация Vivus может продолжаться в старых координатах
  • происходит скачок при первом resize event
  • наблюдаются временные искажения пропорций

Особенно это заметно при responsive SVG внутри flex/grid контейнеров.


Стабильность анимации и микрофризы

Safari чаще демонстрирует микрофризы при SVG-анимациях из-за особенностей работы рендеринг-пайплайна:

  • при первом запуске Vivus возможна пауза между 0 и 1 кадром
  • при сложных путях первые 10–20% анимации выглядят менее плавными
  • при высокой плотности path наблюдается jitter

Причина заключается в сочетании:

  • ленивой компиляции SVG path
  • позднего построения display list
  • особенностей compositing layer invalidation

Итоговые инженерные особенности интеграции Vivus в Safari

При работе с Vivus в Safari критически важно учитывать задержки и особенности SVG-пайплайна:

  • инициализация после первого кадра обязательна для стабильного getTotalLength
  • сложные path требуют предварительного упрощения геометрии
  • анимации с большим количеством элементов лучше разбивать на группы
  • избегается частый доступ к layout API во время анимации
  • предпочтительно фиксировать размеры SVG для минимизации ресайз-артефактов

Safari требует более строгого контроля за моментом старта анимации и количеством одновременно активных SVG-элементов, иначе визуальная целостность Vivus-анимаций нарушается даже при корректной логике JavaScript.