Полифиллы для старых версий

При использовании библиотеки Vivus основной механизм анимации опирается на свойства SVG, такие как stroke-dasharray и stroke-dashoffset, а также на управление кадровой отрисовкой через requestAnimationFrame. В современных окружениях это работает без дополнительных усилий, однако в старых версиях браузеров возникают ограничения, требующие дополнительных слоёв совместимости.

Ключевая проблема заключается не только в отсутствии современных API, но и в частичной поддержке SVG, нестабильной реализации DOM-методов и различиях в обработке CSS-свойств.


Ограничения старых версий браузеров при работе с Vivus

Отсутствие или неполная реализация SVG

В браузерах уровня Internet Explorer 8 и ниже SVG либо отсутствует, либо реализован частично через альтернативные механизмы. В таких условиях невозможна корректная работа анимации обводки, поскольку:

  • не поддерживается stroke-dasharray
  • отсутствует корректное вычисление длины пути через getTotalLength
  • нарушена работа DOM SVG-узлов

В IE9–IE11 поддержка SVG уже присутствует, но остаются ограничения в анимационных API и вычислениях стилей.


Отсутствие requestAnimationFrame

Механизм Vivus использует плавную покадровую анимацию. В старых браузерах отсутствует requestAnimationFrame, что приводит к:

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

Базовый полифилл реализуется через таймеры:

if (!window.requestAnimationFrame) {
  window.requestAnimationFrame = function (callback) {
    return setTimeout(function () {
      callback(Date.now());
    }, 16);
  };
}

Для более точной эмуляции иногда добавляется отмена кадра:

if (!window.cancelAnimationFrame) {
  window.cancelAnimationFrame = function (id) {
    clearTimeout(id);
  };
}

Полифилл для SVG-методов и DOM API

getComputedStyle

В старых браузерах доступ к вычисленным стилям может отсутствовать или работать нестабильно. Vivus использует стили для вычисления параметров SVG-элементов.

if (!window.getComputedStyle) {
  window.getComputedStyle = function (el) {
    return el.currentStyle;
  };
}

Различие заключается в том, что currentStyle возвращает значения в другом формате, что требует осторожности при обработке строковых значений.


classList

Управление классами SVG-элементов критично для состояния анимации. В старых браузерах отсутствует classList.

if (!('classList' in document.documentElement)) {
  Object.defineProperty(Element.prototype, 'classList', {
    get: function () {
      var element = this;
      return {
        add: function (className) {
          element.className += ' ' + className;
        },
        remove: function (className) {
          element.className = element.className.replace(className, '');
        }
      };
    }
  });
}

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


Array.prototype.forEach

Vivus активно использует обход списков путей SVG. В старых окружениях отсутствует forEach у массивов.

if (!Array.prototype.forEach) {
  Array.prototype.forEach = function (callback, thisArg) {
    for (var i = 0; i < this.length; i++) {
      callback.call(thisArg, this[i], i, this);
    }
  };
}

Object.assign

При конфигурации экземпляра библиотеки часто требуется объединение параметров.

if (typeof Object.assign !== 'function') {
  Object.assign = function (target) {
    if (target == null) {
      throw new TypeError('Cannot convert undefined or null to object');
    }
    var to = Object(target);
    for (var i = 1; i < arguments.length; i++) {
      var source = arguments[i];
      if (source != null) {
        for (var key in source) {
          if (Object.prototype.hasOwnProperty.call(source, key)) {
            to[key] = source[key];
          }
        }
      }
    }
    return to;
  };
}

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

Проблемы вычисления длины пути

Метод getTotalLength() может возвращать некорректные значения или быть недоступным для некоторых типов путей. В таких случаях применяется упрощённая модель:

  • аппроксимация длины через bounding box
  • фиксированные значения длины
  • предварительная калибровка SVG при генерации

Это снижает точность анимации, но сохраняет визуальную целостность эффекта прорисовки.


Отсутствие поддержки stroke-dashoffset

Ключевой механизм Vivus основан на изменении:

  • stroke-dashoffset
  • stroke-dasharray

В старых версиях IE возможны следующие ограничения:

  • игнорирование динамического изменения значений
  • пересчёт только при полной перерисовке DOM
  • отсутствие плавной интерполяции

Для компенсации используется имитация через постепенное изменение видимости элементов или разбиение пути на сегменты.


Эмуляция requestAnimationFrame через fallback-таймер

При невозможности использования нативного API применяется временной цикл:

var lastTime = 0;

function fallbackRAF(callback) {
  var currTime = Date.now();
  var timeToCall = Math.max(0, 16 - (currTime - lastTime));
  var id = setTimeout(function () {
    callback(currTime + timeToCall);
  }, timeToCall);
  lastTime = currTime + timeToCall;
  return id;
}

Такая реализация приближает поведение к 60 FPS, но не гарантирует стабильность на слабых устройствах.


Обработка отсутствующих SVG DOM методов

Некоторые браузеры не предоставляют полноценный набор методов для работы с SVG-элементами.

createSVGPoint и аналоги

if (!document.createSVGPoint) {
  document.createSVGPoint = function () {
    return {
      x: 0,
      y: 0
    };
  };
}

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


Особенности событийной модели

Старые версии IE используют альтернативную систему событий:

  • attachEvent вместо addEventListener
  • отсутствие фазы capture
  • иная структура объекта события

Переходный слой:

function addEvent(el, event, handler) {
  if (el.addEventListener) {
    el.addEventListener(event, handler, false);
  } else if (el.attachEvent) {
    el.attachEvent('on' + event, handler);
  }
}

Ограничения производительности при использовании полифиллов

Использование полифиллов в контексте SVG-анимации приводит к дополнительным затратам:

  • увеличение времени инициализации
  • рост нагрузки на главный поток
  • ухудшение плавности при большом количестве путей
  • необходимость ручной оптимизации DOM

Особенно заметно это при сложных иллюстрациях, содержащих десятки или сотни SVG-путей.


Стратегия деградации функциональности

В условиях ограниченной поддержки браузера применяется каскадное снижение сложности:

  • отключение анимации и отображение финального состояния
  • замена анимации на мгновенное появление
  • использование статических изображений вместо SVG
  • частичная прорисовка контуров без интерполяции

Такой подход позволяет сохранять работоспособность интерфейса без полного отказа от визуализации.