diff --git a/packages/react-native/ReactCommon/react/renderer/animated/drivers/FrameAnimationDriver.cpp b/packages/react-native/ReactCommon/react/renderer/animated/drivers/FrameAnimationDriver.cpp index 46af79a137bb..c66dcf80b071 100644 --- a/packages/react-native/ReactCommon/react/renderer/animated/drivers/FrameAnimationDriver.cpp +++ b/packages/react-native/ReactCommon/react/renderer/animated/drivers/FrameAnimationDriver.cpp @@ -49,15 +49,33 @@ void FrameAnimationDriver::onConfigChanged() { frames_.push_back(frameValue); } toValue_ = config_["toValue"].asDouble(); + deferredStart_ = true; } -bool FrameAnimationDriver::update(double timeDeltaMs, bool /*restarting*/) { +bool FrameAnimationDriver::update(double timeDeltaMs, bool restarting) { if (auto node = manager_->getAnimatedNode(animatedValueTag_)) { if (!startValue_) { startValue_ = node->getRawValue(); } + if (deferredStart_ && restarting) { + // On the very first update after start: output the starting value + // (frame 0) and defer the time anchor. The base class will re-anchor + // startFrameTimeMs_ on the next call, so elapsed time is measured + // from the first frame that has actually been rendered — not from + // when startAnimatingNode was dispatched. + // + // This prevents skipping initial frames when the UI thread is busy + // with layout/mount work between animation start and first composite. + node->setRawValue( + startValue_.value() + frames_[0] * (toValue_ - startValue_.value())); + markNodeUpdated(node->tag()); + startFrameTimeMs_ = -1; + deferredStart_ = false; + return false; + } + const auto startIndex = static_cast(std::round(timeDeltaMs / SingleFrameIntervalMs)); assert(startIndex >= 0); diff --git a/packages/react-native/ReactCommon/react/renderer/animated/drivers/FrameAnimationDriver.h b/packages/react-native/ReactCommon/react/renderer/animated/drivers/FrameAnimationDriver.h index 7bcbc4a04484..5c2933b44a2b 100644 --- a/packages/react-native/ReactCommon/react/renderer/animated/drivers/FrameAnimationDriver.h +++ b/packages/react-native/ReactCommon/react/renderer/animated/drivers/FrameAnimationDriver.h @@ -35,6 +35,7 @@ class FrameAnimationDriver : public AnimationDriver { std::vector frames_{}; double toValue_{0}; std::optional startValue_{}; + bool deferredStart_{true}; }; } // namespace facebook::react