Course Menu

Using d3-interpolate-path and Animated to Animate Simple SVG Paths

The d3-interpolate SVG path interpolation requires the DOM in order to parse the path. We don't have access to it since we are in React Native. There is however d3-interpolate-path which operates on strings alone. I do not recommend using this module necessarily as it doesn't work well, but we'll use it to show the same technique we used before but for SVGs.

Here we are using react-native-svg to render SVGs. We have 2 paths, one is a small circle, and the second is a larger circle. We can use the same technique as before and use our listener callback to animate from one path to the next.

import Svg, { Path } from "react-native-svg";
import { interpolatePath } from "d3-interpolate-path";

const startPath = `M45,50a5,5 0 1,0 10,0a5,5 0 1,0 -10,0`;
const endPath = `M20,50a30,30 0 1,0 60,0a30,30 0 1,0 -60,0`;

export default class animations extends Component {
  state = {
    animation: new Animated.Value(0),
  };

  handlePress = () => {
    Animated.sequence([
      Animated.timing(this.state.animation, {
        toValue: 1,
        duration: 500,
      }),
      Animated.delay(1500),
      Animated.timing(this.state.animation, {
        toValue: 0,
        duration: 500,
      }),
    ]).start();
  };

  render() {
    return (
      <View style={styles.container}>
        <TouchableWithoutFeedback onPress={this.handlePress}>
          <Svg width={150} height={150}>
            <Path
              d={startPath}
              stroke="black"
              ref={(path) => (this._path = path)}
            />
          </Svg>
        </TouchableWithoutFeedback>
      </View>
    );
  }
}

Just like before we have a listener and we do our path interpolation. The listener will always call us back regardless of which direction the animation is moving. So we have a sequence that will animate forward to 1, delay, and then animate backwards. We'll have our path interpolated to a larger circle, and then animate back to it's start.

  componentWillMount() {
    const pathInterpolate = interpolatePath(startPath, endPath);

    this.state.animation.addListener(({ value }) => {
      const path = pathInterpolate(value);
      this._path.setNativeProps({
        d: path,
      });
    });
  }

Code