Я пытаюсь сделать обратный отсчет [n sec] с помощью Framer Motion в приложении React, но когда я пытаюсь изменить текст, отображаемый на экране после [n sec], обратный отсчет доходит до 0 секунд до изменения текста случается.
Вот код, который вносит это изменение:
const [status, setStatus] = useState("Waiting...");
const count = useMotionValue(5);
const time = useTransform(count, Math.round);
useEffect(() => {
const animation = animate(count, 0, { duration: 5 });
setTimeout(() => {
setStatus("Finished!");
}, 5 * 1000);
return animation.stop;
}, []);
Репозиторий GitHub для воспроизведения этого доступен здесь: https://github.com/jpfragoso30/jp-framer-sandbox/tree/main
Я попробовал использовать метод onUpdate для анимации, чтобы проверить, не является ли проблема асинхронности.
const animation = animate(count, 0, { duration: 5, onUpdate: (value) => { if (value === 0) setStatus("Finished!"); }, });
И .then, когда анимация заканчивается.
const animation = animate(count, 0, { duration: 5, }).then(() => setStatus("Finished!"));;
Во всех этих попытках я получаю один и тот же результат: «Готово!» текст имеет задержку, и я не думаю, что анимация засчитывается естественным образом, если это имеет смысл.
Вы бы попробовали с обещанием?
useEffect(() => {
const controls = animate(count, 0, { duration: 5 });
controls.then(() => {
setStatus("Finished!");
});
return () => controls.stop();
}, []);
Из-за особенностей useState
с асинхронными функциями, такими как animate
, есть еще одна проблема, связанная с задержкой.
Во-первых, метод преобразования значения счета должен быть максимальным, чтобы начать отсчет с 0, и переходить к 0 только тогда, когда у вас есть абсолютный ноль.
const time = useTransform(count, Math.ceil);
and also, to make the time go "natural", you must declare a "linear" movement
const animation = animate(count, 0, {
duration: 5,
ease: "linear",
}).then(() => setStatus("Finished!"));
Большое спасибо! Да, я забыл, что использую Math.round, и это повлияло на время. И приятно знать, что «линейное» значение позволяет считать их настоящими часами. Отличная работа, Сергий!
Я попробовал, но, похоже, это не работает. Похоже, .then я тоже пытался использовать, но у вас все реализовано правильно.