Очередь анимации в цикличном requestAnimationFrame
Подскажите, как можно реализовать очередь для анимации если используется цикличный requestAnimationFrame?
function animate() { render(); requestAnimationFrame(animate); } function render() { // код для анимации каких ни будь элементов } animate() |
Во-первых в функции animate должна быть проверка на то, что анимация должна остановиться. Т.е. вызывать requestAnimationFrame больше не нужно, иначе получится бесконечный цикл.
Во-вторых у функции animate есть параметр - время. Его надо использовать, что бы узнавать время от начала анимации или от предыдущего вызова animate, что бы рассчитывать какие произвести изменения. Условная схема такая let tbeg; let tlast; function animate(t) { tbeg ??= t; tlast ?? = t const dtbeg = t - tbeg; // прошло от начала анимации const dtlast = t - tlast; // прошло от прошлой анимации render(); // расчет и внесение изменений с учетом dtbeg и/или dtlast tlast = t; if (какое то условие окончания) return; // Завершить анимацию? requestAnimationFrame(animate); } function render() { // код для анимации каких ни будь элементов } animate(performance.now()) Примеры можно посмотреть тут https://developer.mozilla.org/en-US/...AnimationFrame |
Цитата:
|
Если вы используете Three.js, то и пользуйтесь тем, что он дает.
Цикл отрисовки вообще не останавливается. Каждые 1/60 сек (при частоте экрана 60гц) происходит перерисовка экрана с учетом тех изменений, которые были внесены (если браузер не занят орбаботкой длинной задачи). requestAnimationFrame просто дает возможность внести изменения перед перерисовкой с учетом времени. Он представляет базовый уровень, на основе которого можно сделать что угодно, но это именно надо делать самому. Вызовов requestAnimationFrame может быть много (много циклов). И когда наступает время перерисовки страницы, вызываются все функции, зарегистрированные к этому моменту. |
Цитата:
|
Цитата:
Зачем постоянный цикл? Если нет изменений, то и вызывать ничего не надо. Когда есть какие то изменения, то для них запускается цикл requestAnimationFrame Цитата:
|
Цитата:
|
>>Хорошо, тогда давайте будем отталкиваться от Three.js. Не знаете как можно сделать очередь анимаций для Three.js?
Так же как и всегда запускать следующую анимацию после окончания предыдущей и так в порядке очереди. Возможно у тебя возникли сложности с определением события "конец анимации"?. Как пример простого вызова последовательных анимаций мой пост 10ти летней давности =). https://javascript.ru/forum/misc/496...tml#post326928 |
Цитата:
<div id="moved" style="position: absolute;width:30px;height: 30px;background: red;"></div> <br> <input type="button" onclick="but1()" value="кнопка 1"> <br> <script type="text/javascript"> function but1 (){ const element = document.getElementById("moved"); animateMove( element , 800 , 100 , 1500) .then ( () => animateMove( element , -750 , 10 , 200) ) .then ( () => animateMove( element , 150 , -60 , 1000) ) .then ( () => { element.style.background = ("#" + ( Math.random() * (999-100)+100 )).substr(0,4) ; element.style.top = "30px"; element.style.left = "100px"; }) } /* С async/await async function but1 (){ const element = document.getElementById("moved"); await animateMove( element , 800 , 100 , 1500); await animateMove( element , -750 , 10 , 200); await animateMove( element , 150 , -60 , 1000); element.style.background = ("#" + ( Math.random() * (999-100)+100 )).substr(0,4) ; element.style.top = "30px"; element.style.left = "100px"; } */ function animateMove ( element , x , y , time = 1000){ const statrX = element.offsetLeft; const startY = element.offsetTop; const startTime = performance.now(); return new Promise ( (resolve) => { const animate = function (timenow){ const EA = (timenow - startTime) / time; if (EA > 1) { resolve(); } else { element.style.left = startX + (x * EA) + "px"; element.style.top = startY + (y * EA) + "px"; requestAnimationFrame(animate ); } }; animate(startTime); }) } </script> |
Я имею ввиду несколько другое понятие очереди. Например этот же код (я его немного исправил), если несколько раз нажимать на кнопку - анимация будет воспроизводится по новой. А вот каким образом сделать так, чтоб каждое нажатие на кнопку ставило запуск новой функции анимации в некую очередь, и анимация воспроизводилась одна после другой?
1 нажатие на кнопку => animate() 2 нажатие на кнопку => animate() animate() 3 нажатие на кнопку => animate(), animate(), animate() (при условии что анимация вызванная первым нажатием ещё не завершилась) <div id="moved" style="position: absolute;width:30px;height: 30px;background: red; pointer-events: none;"></div> <br> <input type="button" onclick="but1()" value="кнопка 1"> <br> <script type="text/javascript"> function but1 (){ const element = document.getElementById("moved"); animateMove( element , 500 , 100 , 1500) } /* С async/await async function but1 (){ const element = document.getElementById("moved"); await animateMove( element , 800 , 100 , 1500); await animateMove( element , -750 , 10 , 200); await animateMove( element , 150 , -60 , 1000); element.style.background = ("#" + ( Math.random() * (999-100)+100 )).substr(0,4) ; element.style.top = "30px"; element.style.left = "100px"; } */ function animateMove ( element , x , y , time = 1000){ const startX = element.offsetLeft; const startY = element.offsetTop; const startTime = performance.now(); return new Promise ( (resolve) => { const animate = function (timenow){ const EA = (timenow - startTime) / time; if (EA > 1) { resolve(); } else { element.style.translate = `${startX + (x * EA)}px ${startY + (y * EA)}px`; requestAnimationFrame(animate); } }; animate(startTime); }) } </script> |
Часовой пояс GMT +3, время: 04:21. |