2015-11-25 2 views
2

Используя setInterval или RequestAnimationFrame, я хотел бы получить значение прогрессии от lerping между X и Y. Предполагая, что X равно 0, а Y равно 1, я хочу иметь 0, когда он начинается, 0,5 в половине и 1 когда закончите. Я бы хотел, чтобы это произошло в заданные сроки, скажем, 5 секунд. Это означает, что половина значения 0,5 произойдет, когда setInterval/RequestAnimationFrame достигнет 2,5 секунд. Наконец, я бы хотел, чтобы он выполнял pingPong, поэтому, когда он достигает 5 секунд, значения уменьшаются и не увеличиваются, такие как 0,9, 0,8, 0,7 и т. Д., А затем снова начинаются с 0, 0,1, 0,2 ...Как задерживаться вперед и назад между двумя значениями X, Y в цикле?

Любые советы или предложения?

Спасибо!

+1

Пробовали ли вы что-нибудь? Где ты застрял? –

+0

Чтобы уточнить, что @AramilRey спросил; что вы пробовали? Какие исследования вы сделали? Можете ли вы предоставить фрагменты, чтобы продемонстрировать, что вы на самом деле пытались решить проблему самостоятельно? (Простой поиск в Google предоставил бы вам знания, необходимые для решения этого вопроса.) Вы не должны полагаться на сообщество SO, чтобы выполнять вашу работу за вас. –

+0

http://jsbin.com/picuwe/2/edit?js,output – punkbit

ответ

5

Основная формула для линейной интерполяции будет нечто вроде

InterpolatedValue = X*t + (X-Y)*(1-t) 

, где X и Y являются оценено для интерполяции между и t является параметром между 0 и 1 определяющей степенью интерполяции; 0 - X и 1 - Y. Кроме того, вы хотели бы иметь некоторое периодическое движение с длиной периода 5, чередуя направление интерполяции; это может быть достигнуто следующим образом. Если t является неотрицательное число растет с течением времени, вычислить

t' = t - t/10 

удалить все предыдущие периоды, которые произошли и

t'' = t'  : t' in [0,5) 
     5 - t' : t' in [5,10) 

, а затем установить

t''' = t'/5 

нормализовать параметр в [0,1] и использовать базовую формулу интерполяции с самого начала.

Обратите внимание, что производится линейная интерполяция и различные другие методы here.

1

Из вашего описания, в любом данном кадре есть 6 штук состояние:

  1. Время начала текущего Lerp
  2. Lerp TimeSpan
  3. Текущее направление
  4. Текущее значение времени
  5. Start
  6. Конечное значение

Из них можно рассчитать требуемое значение прогресса, говорят:

function progressValue(startTime, lerpSpanSeconds, dir, 
         currentTime X, Y, dir, currentTime) { 
    // lerp 
    return 0.42; 
} 

Для requestAnimationFrame, you need a simple callback to pass in. То есть функция должна знать все, что ей нужно, кроме того, что она может получить при ее запуске. Здесь, когда он запускается, ему просто нужно получить текущее время и выполнить остальное оттуда.

function animableThing() { 
    var startTime = 7; 
    var lerpSpanSeconds = 3; 
    var dir = +1; 
    var X = 0; 
    var Y = 1; 
    var currentTime = GetCurrentUnicornTime(); 
    var thingToAnimate = document.getElementById('myAnimableElement'); 

    var progress = progressValue(startTime, lerpSpanSeconds, dir, 
      currentTime, X, Y, dir, currentTime); 
    // reverse when we hit the end 
    if(progress > Y) { 
     dir *= -1; 
     startTime = currentTime; 
     progress = Y; 
    } 

    DrawAnimationThing(thingToAnimate, progress); 

    // continue the animation 
    window.requestAnimationFrame(animableThing); 
} 

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

function MotherOfAnimableThings(startTime, lerpSpanSeconds, dir, X, Y, 
    thingToAnimate) 
{ 
    // Passed in variables have scope outside the animableThing, these 
    // will be private to the animableThing function. 
    // Consider defaulting or validation here 

    // Construct a new function freshly each time the Mother is called, 
    // and return it to the caller. Note that we assign a variable here 
    // so that we can re-call RequestAnimationFrame to continue the loop 
    var callback = (function() { 
     var currentTime = GetCurrentUnicornTime(); 
     var progress = progressValue(startTime, lerpSpanSeconds, dir, 
       currentTime, X, Y, dir, currentTime); 
     // reverse when we hit the end 
     if(progress > Y) { 
      dir *= -1; 
      startTime = currentTime; 
      progress = Y; 
     } 

     DrawAnimationThing(thingToAnimate, progress); 

     window.requestAnimationFrame(callback); 
    }); 
    return callback; 
} 

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

С вышеуказанным мы просто должны позвонить Мать, чтобы создать функцию animableThing и вызвать с ней запрос RequestAnimationFrame. С этого момента он внутренне вызывает RequestAnimationFrame, чтобы продолжить цикл.

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

var animableThing = MotherOfAnimableThings(...); 
window.requestAnimationFrame(animableThing); 
// ... later 
animableThing.stop = true; // it should stop on the next frame 

 Смежные вопросы

  • Нет связанных вопросов^_^