Java, UX, HTML, CSS, WEB-design

Краткий обзор математики анимации с помощью JavaScript

Краткое описание по статье Краткий обзор математики анимации с помощью JavaScript

Название: Краткий обзор математики анимации с помощью JavaScript . Краткое описание: [ad_1] ⭐ Кристиа . Дата публикации: 20.02.2022 . Автор: Алишер Валеев .

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

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

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

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

[ad_1]

  • Кристиан Хайльманн

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

Краткий обзор математики анимации с помощью JavaScript

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

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

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

В школе я ненавидел математику. Это была ужасная, сухая и скучная вещь с затхлыми старыми книгами и очень теоретическими задачами. Хуже того, многие задачи были повторяющимися, с простым логическим изменением на каждой итерации (деление чисел вручную, дифференциалы и т. д.). Именно по этой причине мы изобрели компьютеры. Достаточно сказать, что большая часть моей домашней работы по математике на самом деле была сделана моим верным Commodore 64 и некоторыми строками Basic, а я просто скопировал результаты позже.

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

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

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

Переход от 0 к 1 без скуки

Если вы только начали программировать и вас просят перейти от 0 к 1 с несколькими промежуточными шагами, вы, вероятно, пойдете на for петля:

for ( i = 0; i <= 1; i += 0.1 ) {
  x = i;
  y = i;
…
}

Это приведет к линии на графике, которая составляет 45 градусов. Ничто в природе не движется с такой точностью:

График под углом 45 градусов, результат простого цикла for

Простой способ сделать это движение более естественным — просто умножить значение само на себя:

for ( i = 0; i <= 1; i += 0.1 ) {
  x = i;
  y = i * i;
}

Это означает, что 0.1 является 0.01, 0.2 является 0.04, 0.3 является 0.09, 0.4 является 0.16, 0.5 является 0.25 и так далее. В результате получается кривая, которая начинается ровно, а затем становится круче к концу:

график значения, умноженного на себя

Вы можете сделать это еще более выраженным, продолжая умножать или используя «в степени» Math.pow() функция:

for ( i = 0; i <= 1; i += 0.1 ) {
  x = i;
  y = Math.pow( i, 4 );
}

график с несколькими умножениями

Это один из приемов функций плавности, используемых в таких библиотеках, как jQuery и YUI, а также в переходах и анимации CSS в современных браузерах.

Вы можете использовать это таким же образом, но есть еще более простой вариант для получения значения от 0 до 1, которое соответствует естественному движению.

Не грех, просто естественное движение

Синусоидальные волны, вероятно, лучшая вещь для плавной анимации. Они случаются в природе: посмотрите на источник с тяжестью на нем, морские волны, звук и свет. В нашем случае мы хотим плавно перейти от 0 к 1.

Чтобы создать движение, которое плавно переходит от 0 к 1 и обратно к 0, мы можем использовать синусоиду, которая проходит от 0 до π за несколько шагов. Полная синусоида, идущая от 0 до π × 2 (т. е. весь круг), приведет к значениям от -1 до 1, а нам это не нужно (пока).

var counter = 0;

// 100 iterations
var increase = Math.PI / 100;

for ( i = 0; i <= 1; i += 0.01 ) {
  x = i;
  y = Math.sin(counter);
  counter += increase;
}

половина синусоиды

Небольшое отступление о числах для синуса и косинуса: Обе Math.sin() а также Math.cos() взять в качестве параметра угол, который должен быть в радианах. Однако людям гораздо легче читать градусы в диапазоне от 0 до 360. Вот почему вы можете и должны конвертировать между ними с помощью этой простой формулы:

var toRadian = Math.PI / 180;
var toDegree = 180 / Math.PI;

var angle = 30;

var angleInRadians = angle * toRadian;
var angleInDegrees = angleInRadians * toDegree;

Вернемся к нашим синусоидам. Вы можете играть с этим много. Например, вы можете использовать абсолютное значение полного цикла 2 × π:

var counter = 0;
// 100 iterations
var increase = Math.PI * 2 / 100;

for ( i = 0; i <= 1; i += 0.01 ) {
  x = i;
  y = Math.abs( Math.sin( counter ) );
  counter += increase;
}

абсолютное значение синусоиды

Но опять же, это выглядит грязно. Если вы хотите полный вверх и вниз, без разрыва посередине, то вам нужно сдвинуть значения. Вы должны разделить синус наполовину, а затем добавить к нему 0,5:

var counter = 0;
// 100 iterations
var increase = Math.PI * 2 / 100;

for ( i = 0; i <= 1; i += 0.01 ) {
  x = i;
  y = Math.sin( counter ) / 2 + 0.5;
  counter += increase;
}

половинчатая и сдвинутая синусоида

Итак, как вы можете использовать это? Иметь функцию, которая возвращает от -1 до 1 для того, что вы ей подаете, может быть очень здорово. Все, что вам нужно сделать, это умножить его на нужные вам значения и добавить смещение, чтобы избежать отрицательных чисел.

Например, посмотрите эту демонстрацию движения синуса:

Демонстрация синусоидального скачка

Выглядит аккуратно, не правда ли? Многие хитрости уже есть в CSS:

.stage {
  width:200px;
  height:200px;
  margin:2em;
  position:relative;
  background:#6cf;
  overflow:hidden;
}

.stage div {
  line-height:40px;
  width:100%;
  text-align:center;
  background:#369;
  color:#fff;
  font-weight:bold;
  position:absolute;
}

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

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

var banner = document.querySelector( '.stage div' ),
    start = 0;
function sine(){
  banner.style.top = 50 * Math.sin( start ) + 80 + 'px';
  start += 0.05;
}
window.setInterval( sine, 1000/30 );

Начальное значение постоянно изменяется, и с Math.sin() мы получаем красивое волновое движение. Мы умножаем это на 50, чтобы получить более широкую волну, и добавляем 80 пикселей, чтобы центрировать ее в элементе сцены. Да, элемент имеет высоту 200 пикселей, а 100 — это половина этого значения, но поскольку высота баннера составляет 40 пикселей, нам нужно вычесть половину этого значения, чтобы отцентрировать его.

Сейчас это простое движение вверх-вниз. Однако ничто не мешает вам сделать его более интересным. Коэффициент умножения 50, например, может быть самой синусоидой с другим значением:

var banner = document.querySelector( '.stage div' ),
    start = 0,
    multiplier = 0;
function sine(){
  multiplier = 50 * Math.sin( start * 2 );
  banner.style.top = multiplier * Math.sin( start ) + 80 + 'px';
  start += 0.05;
}
window.setInterval( sine, 1000/30 );

Результатом этого является баннер, который, кажется, предварительно перемещается вверх и вниз. Когда-то и на очень медленном Commodore 64 вычисление синусоидальной волны в реальном времени было слишком медленным. Вместо этого у нас были инструменты для создания таблиц синусов (массивов, если хотите), и мы наносили их напрямую. Одним из инструментов для создания отличных синусоидальных волн, чтобы у вас мог прыгать текст прокрутки, был Wix Bouncer:

Wixbouncer — инструмент для создания синусоид

Круги на песке, круглые и круглые…

Круговое движение — это красота. Это радует глаз, напоминает нам о прялках и земле, на которой мы стоим, и в целом имеет ощущение «это не компьютерные штучки». Математика построения чего-либо на круге несложна.

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

Синкос

Как это относится к кругу? Что ж, довольно просто найти прямоугольный треугольник в окружности в каждой его точке:

Круг

Это означает, что если вы хотите нарисовать что-то на окружности (или нарисовать ее), вы можете сделать это с помощью цикла, синуса и косинуса. Полный круг равен 360° или 2 × π в радианах. Мы могли бы попробовать, но сначала нужно написать код для построения графика.

Быстрая процедура построения DOM

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

Plot = function ( stage ) {

  this.setDimensions = function( x, y ) {
    this.elm.style.width = x + 'px';
    this.elm.style.height = y + 'px';
    this.width = x;
    this.height = y;
  }
  this.position = function( x, y ) {
    var xoffset = arguments[2] ? 0 : this.width / 2;
    var yoffset = arguments[2] ? 0 : this.height / 2;
    this.elm.style.left = (x - xoffset) + 'px';
    this.elm.style.top = (y - yoffset) + 'px';
    this.x = x;
    this.y = y;
  };
  this.setbackground = function( col ) {
    this.elm.style.background = col;
  }
  this.kill = function() {
    stage.removeChild( this.elm );
  }
  this.rotate = function( str ) {
    this.elm.style.webkitTransform = this.elm.style.MozTransform =
    this.elm.style.OTransform = this.elm.style.transform =
    'rotate('+str+')';
  }
  this.content = function( content ) {
    this.elm.innerHTML = content;
  }
  this.round = function( round ) {
    this.elm.style.borderRadius = round ? '50%/50%' : ’;
  }
  this.elm = document.createElement( 'div' );
  this.elm.style.position = 'absolute';
  stage.appendChild( this.elm );

};

Единственное, что здесь может быть новым, — это трансформация с разными префиксами браузера и позиционирование. Люди часто делают ошибку, создавая div с размерами w а также h а затем установите его на x а также y на экране. Это означает, что вам всегда придется иметь дело со смещением высоты и ширины. Вычитая половину ширины и высоты перед позиционированием div, вы действительно устанавливаете его там, где хотите — независимо от размеров. Вот доказательство:

офсетный выпуск

Теперь давайте воспользуемся этим, чтобы нарисовать 10 прямоугольников по кругу, хорошо?

Простой круг

var stage = document.querySelector('.stage'),
    plots = 10;
    increase = Math.PI * 2 / plots,
    angle = 0,
    x = 0,
    y = 0;

for( var i = 0; i < plots; i++ ) {
  var p = new Plot( stage );
  p.setBackground( 'green' );
  p.setDimensions( 40, 40 );
  x = 100 * Math.cos( angle ) + 200;
  y = 100 * Math.sin( angle ) + 200;
  p.position( x, y );
  angle += increase;
}

Нам нужно 10 предметов в круге, поэтому нам нужно найти угол, под которым мы хотим их расположить. Полный круг — это два раза Math.PI, так что все, что нам нужно сделать, это разделить это. Позиции x и y наших прямоугольников можно рассчитать по углу, под которым они должны быть. X — это косинус, а y — это синус, как объяснялось ранее в отрывке о Пифагоре. Все, что нам нужно сделать, это центрировать круг, который мы рисуем на сцене (200,200 находится в центре сцены), и мы закончили. Мы нарисовали круг радиусом 100 пикселей на холсте за 10 шагов.

Проблема в том, что это выглядит ужасно. Если мы действительно хотим изобразить предметы по кругу, то их углы также должны указывать на центр, верно? Для этого нам нужно вычислить тангенс прямоугольного квадрата, как объясняется на этой очаровательной странице «Математика — это весело». В JavaScript мы можем использовать Math.atan2() как ярлык. Результат выглядит намного лучше:

Тансеркл

var stage = document.querySelector('.stage'),
    plots = 10;
    increase = Math.PI * 2 / plots,
    angle = 0,
    x = 0,
    y = 0;

for( var i = 0; i < plots; i++ ) {
  var p = new Plot( stage );
  p.setBackground( 'green' );
  p.setDimensions( 40, 40 );
  x = 100 * Math.cos( angle ) + 200;
  y = 100 * Math.sin( angle ) + 200;
  p.rotate( Math.atan2( y - 200, x - 200 ) + 'rad' );
  p.position( x, y );
  angle += increase;
}

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

Как насчет анимации круга сейчас? Ну, первое, что нужно сделать, это немного изменить сценарий, потому что мы не хотим продолжать создавать новые сюжеты. Кроме этого, все, что нам нужно сделать, чтобы повернуть круг, — это продолжать увеличивать начальный угол:

var stage = document.querySelector('.stage'),
    plots = 10;
    increase = Math.PI * 2 / plots,
    angle = 0,
    x = 0,
    y = 0,
    plotcache = [];

for( var i = 0; i < plots; i++ ) {
  var p = new Plot( stage );
  p.setBackground( 'green' );
  p.setDimensions( 40, 40 );
  plotcache.push( p );
}

function rotate(){
  for( var i = 0; i < plots; i++ ) {
    x = 100 * Math.cos( angle ) + 200;
    y = 100 * Math.sin( angle ) + 200;
    plotcache[ i ].rotate( Math.atan2( y - 200, x - 200 ) + 'rad' );
    plotcache[ i ].position( x, y );
    angle += increase;
  }
  angle += 0.06;
}

setInterval( rotate, 1000/30 );

Хочу больше? Как насчет вращающегося текстового сообщения на основе этого? Сложность в том, что нам также нужно поворачивать символы на 90° на каждой итерации:

Повернутое сообщение

var stage = document.querySelector('.stage'),
    message="Smashing Magazine ".toUpperCase(),
    plots = message.length;
    increase = Math.PI * 2 / plots,
    angle = -Math.PI,
    turnangle = 0,
    x = 0,
    y = 0,
    plotcache = [];

for( var i = 0; i < plots; i++ ) {
  var p = new Plot( stage );
  p.content( message.substr(i,1) );
  p.setDimensions( 40, 40 );
  plotcache.push( p );
}
function rotate(){
  for( var i = 0; i < plots; i++ ) {
    x = 100 * Math.cos( angle ) + 200;
    y = 100 * Math.sin( angle ) + 200;
    // rotation and rotating the text 90 degrees
    turnangle = Math.atan2( y - 200, x - 200 ) * 180 / Math.PI + 90 + 'deg';
    plotcache[ i ].rotate( turnangle );
    plotcache[ i ].position( x, y );
    angle += increase;
  }
  angle += 0.06;
}

setInterval( rotate, 1000/40 );

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

multiplier = 80 * Math.sin( angle );
for( var i = 0; i < plots; i++ ) {
  x = multiplier * Math.cos( angle ) + 200;
  y = multiplier * Math.sin( angle ) + 200;
  turnangle = Math.atan2( y - 200, x - 200 ) * 180 / Math.PI + 90 + 'deg';
  plotcache[ i ].rotate( turnangle );
  plotcache[ i ].position( x, y );
  angle += increase;
}
angle += 0.06;

И, конечно же, вы также можете перемещать центр круга:

rx = 50 * Math.cos( angle ) + 200;
ry = 50 * Math.sin( angle ) + 200;
for( var i = 0; i < plots; i++ ) {
  x = 100 * Math.cos( angle ) + rx;
  y = 100 * Math.sin( angle ) + ry;
  turnangle = Math.atan2( y - ry, x - rx ) * 180 / Math.PI + 90 + 'deg';
  plotcache[ i ].rotate( turnangle );
  plotcache[ i ].position( x, y );
  angle += increase;
}
angle += 0.06;

В качестве последнего совета, как насчет того, чтобы разрешить только определенный диапазон координат?

function rotate() {
  rx = 70 * Math.cos( angle ) + 200;
  ry = 70 * Math.sin( angle ) + 200;
  for( var i = 0; i < plots; i++ ) {
    x = 100 * Math.cos( angle ) + rx;
    y = 100 * Math.sin( angle ) + ry;
    x = contain( 70, 320, x );
    y = contain( 70, 320, y );
    turnangle = Math.atan2( y - ry, x - rx ) * 180 / Math.PI + 90 + 'deg';
    plotcache[ i ].rotate( turnangle );
    plotcache[ i ].position( x, y );
    angle += increase;
  }
  angle += 0.06;
}
function contain( min, max, value ) {
  return Math.min( max, Math.max( min, value ) );
}

Резюме

Это было просто краткое введение в использование экспонент и синусоид, а также в построение объектов на круге. Попробуйте ввести код и поиграйте с числами. Удивительно, сколько крутых эффектов можно создать, лишь немного изменив радиус или умножив углы. Чтобы вам было проще это сделать, ниже приведены примеры JSFiddle, с которыми можно поиграть:

  • Синусоидальное прыгающее сообщение
  • Двойное синусоидальное сообщение
  • Проблема со смещением при построении графика
  • Распределение элементов по кругу
  • Распределение элементов по кругу с правильными углами
  • Вращение круга ящиков
  • Осциллирующее вращающееся сообщение
  • Вращение сообщения в круговом движении
  • Повернутый скроллер сообщений в штучной упаковке

дальнейшее чтение

  • Анимации SVG и CSS с clip-path
  • Создание «рисованных» анимаций с помощью SVG
  • Новый API веб-анимации
  • Практические методы анимации
  • Рекомендации и примеры анимации пользовательского интерфейса
  • Создание анимации в Photoshop
  • Быстрое прототипирование анимации пользовательского интерфейса в Keynote



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

Заключение

Вы ознакомились с статьей — Краткий обзор математики анимации с помощью JavaScript

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

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

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

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

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