Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added getAnimatableRef function #4533

Merged
merged 4 commits into from
Jun 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions app/src/examples/AnimatableRefExample.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import React, { useState } from 'react';
import { View, StyleSheet, Button } from 'react-native';

import { Rect, Svg } from 'react-native-svg';
import Animated, {
useAnimatedProps,
useSharedValue,
withSpring,
} from 'react-native-reanimated';

type SwitchProps = {
y?: number;
};

class Switch extends React.Component<SwitchProps> {
rectRef: Rect | null = null;

// When an animated version of the Switch is created we want to animate the inner Rect instead of the outer Svg component.
getAnimatableRef() {
return this.rectRef;
}

render() {
return (
<Svg height="310" width="70">
<Rect
x="5"
y="5"
width="60"
height="300"
fill="none"
stroke={'black'}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
stroke={'black'}
stroke="black"

strokeWidth={10}
/>
<Rect
x="10"
y={this.props.y}
width="50"
height="40"
fill="red"
ref={(component) => {
this.rectRef = component;
}}
/>
</Svg>
);
}
}

const AnimatedSwitch = Animated.createAnimatedComponent(Switch);
export default function AnimatableRefExample() {
const [isUp, setIsUp] = useState(true);
const sv = useSharedValue(0);

const animatedProps = useAnimatedProps(() => {
return {
y: sv.value + 10,
};
});

return (
<View style={styles.container}>
<AnimatedSwitch animatedProps={animatedProps} />
<Button
onPress={() => {
sv.value = withSpring(isUp ? 250 : 0, { damping: 18 });
setIsUp(!isUp);
}}
title={`Go ${isUp ? 'down' : 'up'}`}
/>
</View>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
paddingBottom: 200,
},
});
6 changes: 6 additions & 0 deletions app/src/examples/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import AboutExample from './AboutExample';
import AnimatableRefExample from './AnimatableRefExample';
import AnimatedKeyboardExample from './AnimatedKeyboardExample';
import AnimatedListExample from './LayoutAnimations/AnimatedList';
import AnimatedSensorExample from './AnimatedSensorExample';
Expand Down Expand Up @@ -154,6 +155,11 @@ export const EXAMPLES: Record<string, Example> = {

// Basic examples

AnimatableRefExample: {
icon: '⏬',
title: 'Animate inner component',
screen: AnimatableRefExample,
},
AnimatedTextInputExample: {
icon: '🎰',
title: 'Counter',
Expand Down
10 changes: 8 additions & 2 deletions src/createAnimatedComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ type Options<P> = {
interface ComponentRef extends Component {
setNativeProps?: (props: Record<string, unknown>) => void;
getScrollableNode?: () => ComponentRef;
getAnimatableRef?: () => ComponentRef;
}

export interface InitialComponentProps extends Record<string, unknown> {
Expand Down Expand Up @@ -392,14 +393,19 @@ export default function createAnimatedComponent(
let viewName: string | null;
let shadowNodeWrapper: ShadowNodeWrapper | null = null;
let viewConfig;
// Component can specify ref which should be animated when animated version of the component is created.
// Otherwise, we animate the component itself.
const component = this._component?.getAnimatableRef
? this._component.getAnimatableRef()
: this;
if (Platform.OS === 'web') {
viewTag = findNodeHandle(this);
viewTag = findNodeHandle(component);
viewName = null;
shadowNodeWrapper = null;
viewConfig = null;
} else {
// hostInstance can be null for a component that doesn't render anything (render function returns null). Example: svg Stop: https://github.com/react-native-svg/react-native-svg/blob/develop/src/elements/Stop.tsx
const hostInstance = RNRenderer.findHostInstance_DEPRECATED(this);
const hostInstance = RNRenderer.findHostInstance_DEPRECATED(component);
if (!hostInstance) {
throw new Error(
'Cannot find host instance for this component. Maybe it renders nothing?'
Expand Down