Я создал видеопроигрыватель HTML 5, отображающий метаинформацию в качестве наложения. Мета-информация должна отображаться с определенной координатой в определенное время воспроизведения видео над видеоизображением. Оверлейное положение (атрибуты CSS сверху и слева) должно быть анимировано линейно между этими координатами.
Позиции, предоставленные пользователем, хранятся в объекте JavaScript. Например:
{
"0.283079": {
"x": 0.019623233908948195,
"y": 0.05441860465116279
},
"10.302745": {
"x": 0.49686028257456827,
"y": 0.8869767441860466
},
"18.924348": {
"x": 0.9657247514390371,
"y": 0.08046511627906977
}
}
Чтобы реализовать анимацию наложения между 0.283079 s
и 18.924348 s
видео, я линейно интерполировал значения между заданными временными кодами, что привело к следующему результату:
{
0.3: {
"x": 0.020429181741986834,
"y": 0.05582461122653863
},
0.35: {
"x": 0.022810683523910604,
"y": 0.059979231448085354
},
0.4: {
"x": 0.025192185305834374,
"y": 0.06413385166963209
},
0.45: {
"x": 0.027573687087758144,
"y": 0.06828847189117881
},
0.5: {
"x": 0.02995518886968191,
"y": 0.07244309211272554
},
...
18.65: {
"x": 0.95080501675582,
"y": 0.1061291200719866
},
18.7: {
"x": 0.9535241425892902,
"y": 0.10145184817772868
},
18.75: {
"x": 0.9562432684227602,
"y": 0.09677457628347075
},
18.8: {
"x": 0.9589623942562304,
"y": 0.09209730438921293
},
18.85: {
"x": 0.9616815200897006,
"y": 0.087420032494955
}
}
Идея этого подхода состояла в том, чтобы просто прослушать событие timeupdate
чтобы впоследствии использовать значение timeupdate
currentTime
в качестве ключа для доступа к объекту для извлечения интерполированной позиции.
Однако событие timeupdate
срабатывает слишком редко, чтобы достичь жидкой анимации. (Он срабатывает каждые 250 мс в хроме).
Чтобы компенсировать эту проблему, я решил использовать jQuery .animate()
для анимации движения между событиями timeupdate
:
this.element.stop(true, true).animate({
"left" : this.taggingPosition.x + "px",
"top" : this.taggingPosition.y + "px"
}, 250, "linear");
Этот подход приводит к анимации, которая приближается к тому, что предназначено. К сожалению, анимация все еще далека от жидкости, учитывая тот факт, что время timeupdate
может срабатывать с нерегулярными интервалами. Эксперименты с clearQueue
и jumpToEnd
.stop( [clearQueue ] [, jumpToEnd ] )
также не помогли создать более .stop( [clearQueue ] [, jumpToEnd ] )
анимацию.
Как можно добиться гладкой анимации?
Вместо того, чтобы ждать timeupdate
или использовать setInterval
, я рекомендую requestAnimationFrame, который предназначен специально для анимации. Он должен срабатывать примерно 60 раз в секунду, давать или принимать в зависимости от загрузки ЦП и других факторов, определенных браузером. Он имеет дополнительное преимущество, которое браузер обычно синхронизирует с ретрансляцией, чтобы избежать мерцания и/или разрывания экрана, что может случиться на более медленных устройствах, таких как телефоны.
Кроме того, вы можете использовать Popcorn.js с дополнительным модулем Popcorn Base, который более или менее точно выполняет то, что вы пытаетесь сделать. Он имеет интерференцию ключевого кадра и различные функции tweening. Есть много документации и несколько демонстраций. Я рекомендую использовать плагин "style", если вы не хотите создавать свои собственные.