Verification Code with Reanimated and Skia πŸ‘€

Tuesday, December 17, 2024
skia
reanimated
It’s always fascinating to see how adding a human touch to a feature can instantly create empathy with the end user.
I was strongly inspired by this Twitter Post.
This animation is built using Skia and Reanimated. If you have a designer on your team or a creative touch yourself, you could easily recreate similar facial expressions using Rive and link the animation to text input behavior, as shown in this demo.
Nevertheless, I still think it is cool to see how to implement animation with Skia.
In detail you can see the animation split into two components:
  • The TextInput: in the past I made an almost identical one here
  • The Face: I used Skia and some Animated.Views

The Face

The Face is a Square with:
  • 2 Eyebrows: I used a Skia Path to draw the eyebrows
  • 2 Eyes: I used multiple Animated.Views to draw and animate the eyes
  • 1 Mouth: I used a Skia Path to draw the mouth
To animate the Path I built manually the expected paths as SVGs.
const createPath = (
type: 'Happy' | 'Sad' | 'Normal',
{ height, width }: PathParams
) => {
switch (type) {
case 'Happy':
return `M0 ${height / 2} Q${width / 2} ${height} ${width} ${height / 2}`;
case 'Sad':
return `M0 ${height / 2} Q${width / 2} 0 ${width} ${height / 2}`;
case 'Normal':
return `M0 ${height / 2} Q${width / 2} ${height / 2} ${width} ${
height / 2
}`;
}
};
export const DefaultMouthPaths = {
Happy: createPath('Happy', { height: MOUTH_HEIGHT, width: MOUTH_WIDTH }),
Sad: createPath('Sad', { height: MOUTH_HEIGHT, width: MOUTH_WIDTH }),
Normal: createPath('Normal', { height: MOUTH_HEIGHT, width: MOUTH_WIDTH }),
};
export const DefaultEyebrowPaths = {
// Note how the Happy Eyebrow is just the Sad Mouth flipped πŸ˜…
Happy: createPath('Sad', { height: EYEBROW_HEIGHT, width: EYEBROW_WIDTH }),
Sad: createPath('Happy', { height: EYEBROW_HEIGHT, width: EYEBROW_WIDTH }),
Normal: createPath('Normal', {
height: EYEBROW_HEIGHT,
width: EYEBROW_WIDTH,
}),
};
Then it was just a matter of animating the paths using the usePathInterpolation hook from Skia.
const activeMouthPath = usePathInterpolation(
animatedProgress,
[AnimationType.Happy, AnimationType.Normal, AnimationType.Sad],
outputRange
);
Again, there are simpler ways to handle this animation, but I think it is cool to see how to use Skia since in the very end it gives you a tremendous amount of control.
It's crazy how shifting a bit the eyes/mouth/eyebrows can create different faces.

Unlock the beauty of React Native animations

Learn Reanimated, Gesture Handler & Skia with Reanimate.dev

Verification Code Face - Feedback

Share Your Thoughts

I value a lot your feedback! Help me improve by sharing your thoughts, suggestions, or reporting any issues you encounter. If you need assistance, send me an email at hello@reactiive.io