Русский
Русский
English
Статистика
Реклама

Оптимизация графики в Voximplant Kit

Что делать, если сценарий крутой и сложный, но из-за этого начинает тормозить? Данным вопросом задались наши разработчики Voximplant Kit и придумали функцию оптимизации. Продолжая серию обновлений Кита, расскажем, как оптимизация заставила большие сценарии летать и с какими проблемами мы столкнулись в процессе её создания.

Почему надо оптимизировать

Многим знакома проблема производительности, вызванная наличием слишком большого количества элементов на странице. Что это значит? В нашем случае чем больше элементов в сценарии Voximplant Kit, тем больше это влияет на скорость визуализации перемещения блоков по холсту (всех вместе и по отдельности), а также на скорость визуализации перемещения и масштабирования самого холста.

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

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

<svg ... > <---- Холст <g transform="matrix(1,0,0,1,224,444)"> <---- Группа элементов внутри svg  <rect>  <rect>

Реализация

У наших разработчиков появилась идея обернуть SVG в div-элемент, чтобы применять все трансформации сначала к нему, а затем при необходимости к самому SVG-элементу с холстом. После того, как трансформации стали применяться к <div>, мы смогли использовать will-change: transform для их отслеживания:

<div> <---- div-обёртка, к которой применяется оптимизация  <svg ... > <---- Холст   <g> <---- Группа элементов внутри svg    <rect>    <rect>

Но появилась ещё одна проблема использование will-change инициирует создание нового слоя, и чем больше ширина и высота элемента, к которому это св-во применяется, тем больше расходуется оперативной памяти для хранения слоя. Справиться с этим помогло уменьшение масштаба SVG в 10 раз. Так, например, при масштабе холста =200% для слоя сwill-change требовалось300 мегабайтоперативки , а после уменьшения масштаба стало нужно всего около3 мегабайт.

Чтобы это осуществить, выставляем параметр zoom = 0.1 и подключаем к работе методtransformToCenterViewport, после чего применяем те же трансформации к div-элементу:

if (isPerfMode) {  this.el.classList.add('perf-mode');  // Меняем масштаб перед включением performance mode  const prevScale = this._viewportMatrix.a;  const point = this.getViewPortCenter();  const zoom = 0.1;       // Уменьшаем исходный svg, чтобы will-change тратил меньше оперативной памяти  this.transformToCenterViewport(point, zoom, true, false, true);  this.initScale = this._viewportMatrix.a;  this.createMatrix();     this.isPerfMode = true;       // Применяем трансформации к элементу-обертке  this.startPerformance();  this.transformToCenterViewport(point, prevScale, false, false, true);}

Т.к. при переходе в режим оптимизации мы уменьшаем SVG, холст становится очень маленьким и неудобным для работы. Чтобы это исправить, применим обратное масштабирование непосредственно к div-элементу:

public startPerformance(force = false) {  ...  this.isPerformance = true;    // Получаем размер области с блоками и отступ от левого угла вьюпорта  const { x, y, width, height } = this.layers.getBBox();  const initScale = this.initScale;    // Ширина и высота для обёртки и смещение по оси x и y для области с блоками  const wrapW = Math.floor(width * initScale) + 2;  const wrapH = Math.floor(height * initScale) + 2;  const layerX = -x * initScale;  const layerY = -y * initScale;    // this.wrapMatrix - матрица div-элемента с холстом   this.wrapMatrix.e = +(this._viewportMatrix.e + x * this._viewportMatrix.a);   this.wrapMatrix.f = +(this._viewportMatrix.f + y * this._viewportMatrix.d);   this.svgWrapper.style.width = wrapW + 'px';   this.svgWrapper.style.height = wrapH + 'px';   this.svgWrapper.style.transform = this.wrapMatrix.toString();   this.svgWrapper.style.willChange = 'transform'; this.layers.style.transform = `matrix(${initScale},0,0,${initScale},${layerX} ,${layerY} )`;}

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

После завершения масштабирования (событие о скролле), св-во will-change удаляется на 0.1 секунды и затем устанавливается заново. Это заставляет браузер повторно растрировать слой, возвращая пропавшие детали изображения:

// Добавляем 3d трансформацию, чтобы слой не был удаленthis.svgWrapper.style.transform = this.wrapMatrix.toString() + ' translateZ(0)';this.transformFrameId = requestAnimationFrame(() => {  // Устанавливаем св-во will-change для применения в следующем кадре  this.svgWrapper.style.willChange = '';  this.transformFrameId = requestAnimationFrame(() => {    this.svgWrapper.style.willChange = 'transform';    this.svgWrapper.style.transform = this.wrapMatrix.toString();  });});

Осталось внести последний фикс всегда отображать перемещаемый блок поверх других. В JointJS для перемещения блоков и линков по оси Z существуют методы toFront и toBack (аналог z-index в HTML). Принцип их работы заключается в сортировке элементов и перерисовке блоков и линков, это вызывает задержки.

Наши разработчики придумали следующее: блок, с которым мы взаимодействуем, временно ставится в конец дерева элементов внутри SVG (элемент с самым высоким z-index находится в конце списка) на событие mousedown, а затем возвращается на прежнее место на событие mouseup.

Принцип работы

Режим оптимизации можно протестировать во всех браузерах на основе Chromium (Chrome, Opera, Edge, Yandex Browser и т.п.), а также в браузере Safari. Для сценариев, содержащих от 50 блоков, функция включается автоматически. Самостоятельно включить или отключить её можно, перейдя в меню настроек сценария в правом верхнем углу:

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

Ниже для сравнения представлены 2 гифки, демонстрирующие работу в редакторе с выключенным и включенным режимом оптимизации. Но поскольку всегда интереснее потестить самому, смело переходим в свой сценарий Voximplant Kit или, если ещё нет аккаунта, на страницу регистрации.

Без оптимизации работа с холстом и его элементами выглядит примерно так (на разных компьютерах с разными мощностями результат может отличаться):

Подключаем оптимизацию и вуаля!

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

Надеемся, что статья была интересной, мы будем продолжать улучшать продукт и делиться успехами и лайфхаками с вами!

Источник: habr.com
К списку статей
Опубликовано: 24.03.2021 14:22:50
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Блог компании voximplant

Разработка веб-сайтов

Javascript

Программирование

Разработка систем связи

Voximplant

Voximplant kit

Jointjs

Css

Html

Web-разработка

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru