Java, UX, HTML, CSS, WEB-design

Нам понадобится более крупный API!

[ad_1]

  • Джейк Арчибальд

  • 0 Комментарии

Нам понадобится более крупный API!

  • 10 минут чтения

  • Кодирование, CSS, JavaScript, Анимация

Краткое резюме ↬

Всем нравится то, что ходит по Сети, верно? Вспомни, как ты плакал радостными слезами, когда впервые употребил <marquee>? Я делаю. Я чуть не выплакала всю воду из своего тела, глядя на надпись «КЛАССНЫЙ ВЕБ-САЙТ ДЖЕЙКА», качающуюся туда-сюда заглавными засечками.

Конечно, в наши дни мы стали более зрелой отраслью.

Мы узнали, что пользователи не хотят, чтобы веб-сайты выглядели как консоль CSI, переживающая личный кризис; вместо этого мы стремимся к плавным переходам, которые улучшают опыт, а не сами являются им. Что касается API-интерфейсов анимации, нас плохо обслужили, и нам пришлось ковыряться с таймерами, которые на самом деле не были созданы для анимации. Ситуация в этой области неуклонно улучшается, но новая спецификация веб-анимации, похоже, сильно ее встряхнет.

Дальнейшее чтение на SmashingMag:

  • Руководство по CSS-анимации: принципы и примеры
  • Переходы CSS3: слава богу, у нас есть спецификация!
  • Состояние анимации 2014
  • Введение в анимацию ключевых кадров CSS3

Итак, зачем нам нужна новая спецификация анимации? Разве у нас уже недостаточно способов оживить вещи?

Еще после прыжка! Продолжить чтение ниже ↓

Оптимизация способа заставить вещи двигаться
Оптимизация способа заставить вещи двигаться. (Источник изображения)

Давайте анимируем вещь!

Представьте, что мы хотим анимировать что-то по горизонтали из одного левого положения в другое в течение трех секунд, а затем что-то делать по завершении. Мы можем сделать это без JavaScript, используя анимацию CSS, но если начальная и конечная позиции определяются программно, то нам нужно что-то, чем мы можем управлять из скрипта.

С использованием requestAnimationFrame

Если вы выполняете визуальные обновления с помощью JavaScript, вам следует использовать requestAnimationFrame. Он синхронизируется с реальными обновлениями экрана, давая вам как можно больше времени, чтобы все было готово к рендерингу. Если браузер работает на экране с частотой 60 Гц (большинство из них) и ваши кадры могут быть построены менее чем за 60-ю долю секунды, вы получите 60 кадров в секунду (FPS). requestAnimationFrame предотвращает создание кадров, которые не успевают отображаться. Синхронизация с частотой экрана важна; 30 кадров в секунду выглядят более плавно, чем 40 кадров в секунду, потому что 40 не делится на собственные 60 Гц экрана. В HTML5 Rocks есть отличная статья о синхронизации с экраном.

К сожалению, jQuery использует setIntervalчто не так гладко, как requestAnimationFrame. requestAnimationFrame не срабатывает, пока вкладка или окно не видны, что Хорошая вещь™. К сожалению, это создало обратную несовместимость с веб-сайтами, которые полагаются на setIntervalменее оптимальное поведение продолжения работы в фоновом режиме. Вы можете выбрать requestAnimationFrame через плагин. Идите и добавьте это на все свои страницы, используя анимацию jQuery сейчас — я обещаю ждать вас — просто убедитесь, что переключение вкладок не сломает вашу анимацию.

Впрочем, хватит болтать. Вот простая анимация с использованием rafперемещая коробку по горизонтали из 250px к 500px. Обратите внимание, что поле начинается с 0pxтак что есть переход к 250px когда начинается анимация; это доказывает, что мы можем начать анимацию с точки, отличной от текущей отображаемой позиции.

Вот код:

// On button press…
animateLeft(elm, ‘250px’, ‘500px’, function() {
  console.log(“Done!”);
});

// The implementation

function animateLeft(elm, from, to, done) { // Turn our CSS values into numbers // We’re being lazy and assuming they’re in px from = parseInt(from, 10); to = parseInt(to, 10); // Work out the amount we need to move the box var diff = to - from;

var duration = 3000; var startTime = performance.now();

// Set initial position elm.style.transform = ‘translate(’ + from + ‘px, 0)’;

function frame(time) { // How long has the animation been running? var animTime = time - startTime; // Are we done? if (animTime >= duration) { // It’s likely that the last rendered position wasn’t the // final position, so we set it here. elm.style.transform = ‘translate(’ + to + ‘px, 0)’;

  <span class="token function">done<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">else</span> <span class="token punctuation">{</span>
<span class="token comment">  // What position should the box be in?

вар должность знак равно от + (анимтайм / продолжительность * разница);
вяз.стиль.трансформировать знак равно 'перевести(' + должность + 'пкс, 0)';
// Запрос следующего кадра
запросAnimationFrame(Рамка);
}
}
// запрашиваем наш первый кадр
запросAnimationFrame(Рамка);
}

Приведенный выше код является идеальным в соответствии со спецификацией. В рабочем примере мне пришлось иметь дело с префиксами поставщиков на requestAnimationFrame и transform. Мы анимируем с помощью transform и translateскорее, чем leftпотому что они позволяют субпиксельное позиционирование и, следовательно, более плавную анимацию, что является одним из преимуществ, которые Flash так долго имел перед HTML.

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

изображение02-500

Это временная шкала инструментов разработчика Chrome во время выполнения анимации. Каждый кадр выполняет некоторый JavaScript, пересчитывает стиль и макет, рисует поле, а затем отправляет это на графический процессор, который объединяет его на странице. Время прорисовки несколько раз увеличивается, что приводит к толчку в анимации. Это вызвано задержками при взаимодействии с графическим процессором (серые пики) или задержками, вызванными другим JavaScript (желтые пики).

Это подчеркивает узкое место производительности анимации, управляемой JavaScript:

изображение01-500

Здесь еще один фрагмент JavaScript делает некоторые вещи, и на это уходит 250 миллисекунд. Пока это происходит, наша анимация не может двигаться. В реальном мире, это может быть кнопка социальной сети, которая просыпается и делает что-то медленное, или это может быть какой-то ваш собственный скрипт, запускаемый взаимодействием с пользователем. В приведенном выше примере я сделал кнопку, которая выполняет while цикл на 250 миллисекунд (я почти уверен, что этот код есть в каждой кнопке социальных сетей). Если вы нажмете ее во время анимации, она заблокирует анимацию и будет выглядеть неприятно.

Недавно я пел дифирамбы requestAnimationFrame для анимации холста, так почему я ненавижу его сейчас? Анимация на основе JavaScript не является плохой практикой — она дает вам полный контроль кадр за кадром и пиксель за пикселем в сочетании с <canvas> — но возвращаться к земле JavaScript 60 раз в секунду — это излишество для DOM-анимаций, у которых есть определенное начало и конец. В идеале мы хотим рассказать браузеру все о нашей анимации и оставить его делать свое делопока мы занимаемся чем-то другим.

Конечно, у нас это уже есть.

Использование CSS-переходов

.whatever {
   transform: translate(250px, 0);
   transition: transform 3s linear;
}
.whatever:hover {
   transform: translate(500px, 0);
}

CSS-переходы и анимация позволяют браузеру выполнять всевозможные оптимизации, поскольку он знает конечную точку анимации. Они не блокируются JavaScript на некоторых платформах, таких как Chrome для Android и настольный Chrome с включенным многопоточным композитингом в about:flags (ожидайте, что многопоточный композитинг появится в большем количестве браузеров).

Давайте сценарий!

function animateLeft(elm, from, to, done) {
  // Set initial position
  elm.style.transform = ‘translate(’ + from + ’, 0)’;
  // Define the transition type
  elm.style.transition = ‘all 3s linear’;

function transitionEnd(event) { // Beware of bubbled events if (event.target != elm) { return; } // Clear the transition elm.style.transition = ; // We don’t want that listener firing for future anims elm.removeEventListener(‘transitionend’, transitionEnd);

<span class="token function">done<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>

}

// Слушаем конец перехода
вяз.addEventListener('переходный конец', переходКонец);
// начинаем переход
вяз.стиль.трансформировать знак равно 'перевести(' + к + ', 0)';
}

Вот живой пример. Это намного проще, чем наш raf пример, но закралась ошибка. from игнорируется; анимация начинается с текущей позиции элемента, даже если мы явно установили что-то другое. Почему?

// Set initial position
elm.style.transform = ‘translate(’ + from + ’, 0)’;
// Define the transition type
elm.style.transition = ‘all 3s linear’;
// …and later…
// Start the transition
elm.style.transform = ‘translate(’ + to + ’, 0)’;

Изменение свойств в style object не изменяет вычисляемый стиль элемента. Стиль вычисляется только тогда, когда браузеру нужно знать, какое влияние эти стили окажут на страницу (например, когда нужно отрисовать элемент). Элемент не нужно рисовать между двумя присваиваниями elm.style.transformпоэтому первое присваивание игнорируется.

Конечно, мы можем взломать его:

// Set initial position
elm.style.transform = ‘translate(’ + from + ’, 0)’;
// Abracadabra!
elm.offsetWidth;
// Define the transition type
elm.style.transition = ‘all 3s linear’;
// …and later…
// start the transition
elm.style.transform = ‘translate(’ + to + ’, 0)’;

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

изображение03-500

Производительность стабильна на уровне 60 FPS. И мы видим, что каждый кадр представляет собой простую композицию; вся тяжелая работа возложена на GPU.

Однако, опираясь на offsetWidth заставить элемент в исходное положение является хакерским, и вполне возможно, что будущая версия браузера найдет способ оптимизировать перекомпоновкувзломав наш хак.

Рефлоу тоже не обходится без затрат:

изображение00-500

Инструменты разработчика предупреждают нас об этом использовании offsetWidth, потому что браузер вычисляет макет, который он никогда не рисует. Тестовая страница очень проста, поэтому стоимость макета невелика, но в реальном мире все может быть совсем иначе.

Итак, есть ли менее хакерский, более надежный способ?

Введите CSS-анимацию

Анимации CSS имеют явные значения ключевых кадров. Напишем их:

function animateLeft(elm, from, to, done) {
  // Create a style element for our animation
  var style = document.createElement(‘style’);
  // Generate a unique name
  var animName = ‘anim’ + Date.now() + Math.floor(Math.random() * 10000);

// Build the CSS style.textContent = + ’@keyframes ‘ + animName + ’ { ‘ + ‘from { ‘ + ‘transform: translate(’ + from + ’, 0);’ + ’}’ + ‘to {’ ‘transform: translate(’ + to + ’, 0);’ + ’}’ + ’}’;

// Add it to the page document.head.appendChild(style);

function transitionEnd(event) { // Beware of bubbled events if (event.target != elm) { return; } // Clear the animation elm.style.animation = ; // Clean up the DOM document.head.removeChild(style); // Retain the final position elm.style.transform = ‘translate(’ + to + ’, 0)’; // We don’t want that listener firing for future anims elm.removeEventListener(‘animationend’, transitionEnd);

<span class="token function">done<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>

}

// Слушаем конец перехода
вяз.addEventListener('конец анимации', переходКонец);

// Запускаем анимацию
вяз.стиль.анимация знак равно animName + «3 с линейно вперед»;
}

Фу! И все это только для того, чтобы что-то сдвинуть? Это работает, но вся эта работа с DOM тяжела для того, чего мы пытаемся достичь. Кроме того, если анимация прерывается на полпути (например, при изменении стиля анимации), то animationend не будет стрелять — это означает, что наша done обратный вызов не сработает или, что еще хуже, сработает в конце какой-нибудь будущей несвязанной анимации. Здесь нет animationcancel событие.

Веб-анимация, спасите нас от этого беспорядка!

Спецификация веб-анимации только начинается, но она довольно захватывающая. Он привносит в DOM множество производительности анимации и функций синхронизации, которые в настоящее время приходится пробивать библиотекам JavaScript.

Сама спецификация какая-то пугающая. Мое сердце упало, когда я открыл страницу и увидел, что полоса прокрутки становится все меньше и меньше. Но, к счастью, в основном это детали реализации.

Вот как мы напишем нашу анимацию в дивном новом мире веб-анимации:

// Set our start position
elm.style.transform = ‘translate(250px, 0)’;
// Animate to the end position
var anim = elm.animate({
  transform: ‘translate(500px, 0)’
}, 3);
// Do something on completion
anim.onend = function() {
  console.log(‘Done!’);
};

Здесь, elm является HTMLElement. API интуитивно понятен, особенно если вы создавали анимацию с помощью чего-то вроде jQuery.

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

Веб-анимация дает нам скриптовый API для анимации, управляемой браузером, которого очень не хватает. Выше приведен пример «Hello world». Спецификация включает в себя расширенное упрощение, анимацию на основе пути, распараллеливание, синхронизацию, прерывание и адаптацию, и все это таким образом, что браузер может отнять у земли JavaScript и соответствующим образом оптимизировать.

Это еще очень рано, поэтому пока не выбрасывайте свои библиотеки анимации. Но если вы хотите поэкспериментировать с новым API и оставить отзыв, полифилл отслеживает быстро меняющуюся спецификацию. Захватывающие времена!

Сокрушительная редакция
(аль)



[ad_2]
Source: https://smashingmagazine.com

Заключение

Вы ознакомились с статьей — Нам понадобится более крупный API!

Пожалуйста оцените статью, и напишите комментарий.

Похожие статьи

Добавить комментарий

Ваш адрес email не будет опубликован.

Краткое описание по статье Нам понадобится более крупный API!

Название: Нам понадобится более крупный API! . Краткое описание: [ad_1] ⭐ Джейк А . Дата публикации: 14.02.2022 . Автор: Алишер Валеев .

Для чего создан сайт Novosti-Nedeli.ru

Данный сайт посвящен новостям мира и мира технологий . Также тут вы найдете руководства по различным девайсам.

Сколько лет сайту?

Возраст составляет 3 года

Кнопка «Наверх»