Smooth Text Morphing for React Native with Reanimated

Description:

expo-morphing-text is a React Native animation component that allows you to create smooth character morphing transitions between text strings.

It uses React Native Reanimated 3 to animate individual characters as text content changes. The component works across iOS and Android platforms through Expo’s development environment.

Features

  • 🔤 Character Morphing: Animates individual characters during text transitions with smooth interpolation.
  • Reanimated-powered: Uses React Native Reanimated worklets for performant animations on the UI thread.
  • 🎨 Style Customization: Accepts fontSize, color, and custom TextStyle props for visual control.
  • Animation Control: Configurable duration through the animationDuration prop.
  • 🔄 Layout Animations: Supports Reanimated’s entering, exiting, and layout transition props.

See In In Action

Use Cases

  • Loading States: Display animated text during asynchronous operations or data fetching processes.
  • Dynamic Labels: Animate text changes in buttons, badges, or status indicators when application state updates.
  • Onboarding Screens: Create fluid text transitions for tutorial sequences or feature introductions.
  • Live Data Displays: Animate numerical or textual updates in dashboards or real-time monitoring interfaces.

How to Use It

1. Clone the repository and install dependencies.

git clone https://github.com/rit3zh/expo-morphing-text
cd expo-morphing-text
bun install

2. Run the development build on your target platform.

bun ios
# or
bun android

3. The core component is MorphingCharacter, which handles single character animations. The MorphingCharactersList component manages collections of morphing characters.

import { MorphingCharacter } from './components/morph-character';
import { View } from 'react-native';
function App() {
  return (
    <View>
      <MorphingCharacter
        char="A"
        fontSize={48}
        color="#000000"
        animationDuration={300}
      />
    </View>
  );
}

4. The MorphingCharactersList component accepts an array of character objects with layout identifiers. You map your text string to this format before passing it to the component.

import { MorphingCharactersList } from './components/morphing-char-list';
import { FadeIn, FadeOut, Layout } from 'react-native-reanimated';
const chars = [
  { char: 'H', layoutId: 'char-0' },
  { char: 'e', layoutId: 'char-1' },
  { char: 'l', layoutId: 'char-2' },
  { char: 'l', layoutId: 'char-3' },
  { char: 'o', layoutId: 'char-4' }
];
function TextAnimation() {
  return (
    <MorphingCharactersList
      chars={chars}
      fontSize={36}
      color="#333333"
      animationDuration={250}
      entering={FadeIn}
      exiting={FadeOut}
      layout={Layout.springify()}
    />
  );
}

5. Control text changes by updating the chars array. Each character needs a unique layoutId for Reanimated to track layout transitions correctly.

const [text, setText] = useState('Hello');
const [chars, setChars] = useState(
  text.split('').map((char, i) => ({ char, layoutId: `char-${i}` }))
);
function updateText(newText: string) {
  setText(newText);
  setChars(
    newText.split('').map((char, i) => ({ char, layoutId: `char-${i}` }))
  );
}

6. You can apply custom TextStyle props through the fontStyle parameter to match your design system.

<MorphingCharactersList
  chars={chars}
  fontSize={40}
  color="#FF6B6B"
  animationDuration={200}
  fontStyle={{
    fontWeight: '700',
    letterSpacing: 2,
    textTransform: 'uppercase'
  }}
  entering={FadeIn.duration(300)}
  exiting={FadeOut.duration(300)}
  layout={Layout.springify().damping(15)}
/>

7. The component uses useMorphCharAnimation hook internally to generate animated styles. You can reference this implementation if you need to build custom character animations.

API Reference

MorphingCharacter Props

  • char (string, required): The character to display and animate.
  • fontSize (number, required): Font size in pixels for the character.
  • color (string, required): Text color in hex or rgba format.
  • animationDuration (number, required): Duration of the morph animation in milliseconds.
  • fontStyle (TextStyle, optional): Additional React Native TextStyle properties.

MorphingCharactersList Props

  • chars (LayoutChar[], required): Array of character objects with char and layoutId properties.
  • fontSize (number, required): Font size applied to all characters.
  • color (string, required): Text color applied to all characters.
  • animationDuration (number, required): Duration for character animations.
  • fontStyle (TextStyle, optional): Custom text styling for all characters.
  • entering (EntryExitAnimationFunction, optional): Reanimated entering animation function.
  • exiting (EntryExitAnimationFunction, optional): Reanimated exiting animation function.
  • layout (LayoutAnimationFunction, optional): Reanimated layout transition function.

LayoutChar Interface

  • char (string): The character to render.
  • layoutId (string): Unique identifier for layout animation tracking.

Related Resources

  • React Native Reanimated: The animation library that powers the morphing transitions in this component.
  • Expo: The development platform required to run this component.

FAQs

Q: Does this work with bare React Native projects without Expo?
A: The component depends on Expo’s managed workflow. You need to modify imports and configuration to run it in a bare React Native setup with React Native Reanimated installed manually.

Q: Can I animate entire words or sentences instead of individual characters?
A: The component animates at the character level. You concatenate multiple MorphingCharactersList components or modify the implementation to handle word-level transitions.

Q: How do I control the animation easing or spring configuration?
A: You pass Reanimated layout animation functions with custom timing or spring parameters through the layout prop. The entering and exiting props accept animation functions with configuration methods.

Q: What causes performance issues with long text strings?
A: Each character renders as a separate animated view. Strings longer than 50 characters may impact performance on lower-end devices.

Add Comment