Скажем, если я делаю Ease-Out, а затем Легкая анимация перемещения объекта из координаты X1 в координату X2 S шагов с равными интервалами времени. Может ли кто-нибудь предложить формулу для вычисления этих координат движения X?
Формула упрощения и облегчения анимации
Ответ 1
Квадратичное облегчение где:
t = текущее время
б = начальное значение
с = изменение стоимости
д = продолжительность
function (float time, float startValue, float change, float duration) {
time /= duration / 2;
if (time < 1) {
return change / 2 * time * time + startValue;
}
time--;
return -change / 2 * (time * (time - 2) - 1) + startValue;
};
источник: http://gizma.com/easing/
Ответ 2
На самом деле, я бы предпочел использовать функцию, которая получает время в [0; 1] и выведите время в [0; 1], так что мы можем применить результат к любому типу (2D-вектор, 3D-вектор,...).
Решение 1
Для квадратичного ослабления in/out кривая разделяется на две функции в зависимости от t
:
- когда
t
< 0,5:f(t) = square(t)
- когда
t
>= 0,5:f(t) = 1 - square(t - 1) + 0.5
После редукции в C это даст следующее:
float InOutQuadBlend(float t)
{
if(t <= 0.5f)
return 2.0f * square(t);
t -= 0.5f;
return 2.0f * t * (1.0f - t) + 0.5;
}
Решение 2 (Безье)
Еще одна интересная кривая смешения - та, которую дает Безье, которая имеет преимущество, чтобы быть достаточно оптимизированной (нет, если). Вы можете проверить кривую на Wolfram. И вот код C:
float BezierBlend(float t)
{
return square(t) * (3.0f - 2.0f * t);
}
Решение 3 (параметрическая функция)
Edit:
Другой метод, предложенный @DannyYaroslavski, - это простая формула, предложенная здесь.
Он параметрический и получает хорошее ускорение и замедление в/в.
С альфа = 2 вы получаете эту функцию:
Что переводит в C так:
float ParametricBlend(float t)
{
float sqt = square(t);
return sqt / (2.0f * (sqt - t) + 1.0f);
}
Ответ 3
У меня возникла та же проблема: я хотел анимировать свой график (Ease in-out)
.
Мозговой штурм дал мне два пути:
1) Тригонометрическая формула. Во-первых, я написал y=(sin(x/π*10-π/2)+1)/2
, аналогом которого является sin^2((5*x)/π)
float TrygoEase (float x) {
float y=(float)Math.pow(Math.sin(5*x/Math.PI),2);
return y;
}
2) Две параболы. Это было не сложно. Я просто использовал y=2*x*x
для [0;0.5]
и y=-2(x-1)^2+1
для [0.5;1]
float ParabolEase(float x) {
float y=2*x*x;
if(x>0.5f){
x-=1;
y=-2*x*x+1;
}
return y;
}
Используйте эти способы для x=[0;1]
, что также возвращает y=[0;1]
.
Теперь вы можете сравнить эти графики:
Ответ 4
Во всех вышеперечисленных решениях отсутствуют примеры использования.
Нашли хорошее решение здесь:
function animate({timing, draw, duration}) {
let start = performance.now();
requestAnimationFrame(function animate(time) {
// timeFraction goes from 0 to 1
let timeFraction = (time - start) / duration;
if (timeFraction > 1) timeFraction = 1;
// calculate the current animation state
let progress = timing(timeFraction)
draw(progress); // draw it
if (timeFraction < 1) {
requestAnimationFrame(animate);
}
});
}
Пример использования:
animate({
duration: 1000,
timing(timeFraction) { // here you can put other functions
return timeFraction;
},
draw(progress) {
elem.style.width = progress * 100 + '%';
}
});
Другая функция:
function quad(timeFraction) {
return Math.pow(timeFraction, 2)
}
Подробнее здесь