implement setOffset (#52034)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52034

changelog: [internal]

implement `setAnimatedNodeOffset`.

Reviewed By: christophpurrer

Differential Revision: D76604263

fbshipit-source-id: 36b86aada836098f502f8d24af07e2a98adf0446
This commit is contained in:
Samuel Susla
2025-06-16 04:50:47 -07:00
committed by Facebook GitHub Bot
parent eecd07c58b
commit ddafd94124
5 changed files with 88 additions and 3 deletions
@@ -197,3 +197,69 @@ test('animated opacity', () => {
<rn-view opacity="0" />,
);
});
test('moving box by 50 points with offset 10', () => {
let _translateX;
const viewRef = createRef<HostInstance>();
function MyApp() {
const translateX = useAnimatedValue(0);
_translateX = translateX;
return (
<Animated.View
ref={viewRef}
style={[
{
width: 100,
height: 100,
},
{transform: [{translateX}]},
]}
/>
);
}
const root = Fantom.createRoot();
Fantom.runTask(() => {
root.render(<MyApp />);
});
const viewElement = ensureInstance(viewRef.current, ReactNativeElement);
expect(viewElement.getBoundingClientRect().x).toBe(0);
Fantom.runTask(() => {
Animated.timing(_translateX, {
toValue: 50,
duration: 1000, // 1 second
useNativeDriver: true,
}).start();
});
Fantom.runTask(() => {
_translateX.setOffset(10);
});
Fantom.unstable_produceFramesForDuration(500);
// shadow tree is not synchronised yet, position X is still 0.
expect(viewElement.getBoundingClientRect().x).toBe(0);
expect(
// $FlowFixMe[incompatible-use]
Fantom.unstable_getDirectManipulationProps(viewElement).transform[0]
.translateX,
).toBeCloseTo(35, 0.001);
Fantom.unstable_produceFramesForDuration(500);
expect(
// $FlowFixMe[incompatible-use]
Fantom.unstable_getDirectManipulationProps(viewElement).transform[0]
.translateX,
).toBeCloseTo(60, 0.001);
// TODO: this shouldn't be neccessary but C++ Animated still schedules a React state update.
Fantom.runWorkLoop();
});
@@ -123,9 +123,10 @@ void AnimatedModule::setAnimatedNodeValue(
void AnimatedModule::setAnimatedNodeOffset(
jsi::Runtime& /*rt*/,
Tag /*nodeTag*/,
double /*offset*/) {
// TODO(T196512946): missing implementation
Tag nodeTag,
double offset) {
operations_.emplace_back(
SetAnimatedNodeOffsetOp{.nodeTag = nodeTag, .offset = offset});
}
void AnimatedModule::flattenAnimatedNodeOffset(
@@ -245,6 +246,8 @@ void AnimatedModule::executeOperation(const Operation& operation) {
nodesManager_->stopAnimation(op.animationId, false);
} else if constexpr (std::is_same_v<T, SetAnimatedNodeValueOp>) {
nodesManager_->setAnimatedNodeValue(op.nodeTag, op.value);
} else if constexpr (std::is_same_v<T, SetAnimatedNodeOffsetOp>) {
nodesManager_->setAnimatedNodeOffset(op.nodeTag, op.offset);
} else if constexpr (std::is_same_v<T, ConnectAnimatedNodeToViewOp>) {
nodesManager_->connectAnimatedNodeToView(op.nodeTag, op.viewTag);
} else if constexpr (std::is_same_v<
@@ -66,6 +66,11 @@ class AnimatedModule : public NativeAnimatedModuleCxxSpec<AnimatedModule>,
double value{};
};
struct SetAnimatedNodeOffsetOp {
Tag nodeTag{};
double offset{};
};
struct ConnectAnimatedNodeToViewOp {
Tag nodeTag{};
Tag viewTag{};
@@ -105,6 +110,7 @@ class AnimatedModule : public NativeAnimatedModuleCxxSpec<AnimatedModule>,
DisconnectAnimatedNodesOp,
StartAnimatingNodeOp,
StopAnimationOp,
SetAnimatedNodeOffsetOp,
SetAnimatedNodeValueOp,
ConnectAnimatedNodeToViewOp,
DisconnectAnimatedNodeFromViewOp,
@@ -246,6 +246,14 @@ void NativeAnimatedNodesManager::setAnimatedNodeValue(Tag tag, double value) {
}
}
void NativeAnimatedNodesManager::setAnimatedNodeOffset(Tag tag, double offset) {
if (auto node = getAnimatedNode<ValueAnimatedNode>(tag)) {
if (node->setOffset(offset)) {
updatedNodeTags_.insert(node->tag());
}
}
}
void NativeAnimatedNodesManager::stopAnimationsForNode(Tag nodeTag) {
std::vector<int> discardedAnimIds{};
@@ -96,6 +96,8 @@ class NativeAnimatedNodesManager {
void setAnimatedNodeValue(Tag tag, double value);
void setAnimatedNodeOffset(Tag tag, double offset);
// drivers
void startAnimatingNode(