Scalable Vector Graphic (SVG) is an image format that uses vector graphics to display the image you see. They are now popular among developers because they scale to any resolution other advantages of SVGs include:
- Easily Editable: SVG files can be created and edited with any text editor. You can also manipulate the properties with CSS.
- Small File Size: due to the nature of SVGs the resolutions don’t affect the file sizes allowing the file sizes to be minimal when compared to the pixel-based counterparts
- SEO Friendly: because of its XML markup language format SVG is SEO friendly as you can add keywords and descriptions to the image directly.
- They can be animated: We earlier talked about how easy it is to customize and edit SVG files this makes it easy to animate SVG files with CSS and JavaScript
In this article, we will be looking at different ways of manipulating SVG images in React native applications.
Setting up a React Native Project
We will be using the Expo framework to bootstrap our React native application. Make sure you have Node.js/npm on your machine. Open a terminal and run the code below to install the expo-cli
globally
npm install -global expo-cli
After installation, run the code below to create a new react-native project
expo install react-native-svg-tutorial
This will launch an interactive prompt for you to select a template. Choose blank and press the enter/return key to continue the installation
Once the process is complete, navigate to the root of the project directory and run the code below to start the expo development server
expo start react-native-svg-tutorial
You will be presented with an interactive menu similar to the screenshot below
The Expo dev server allows you to test your application locally while in development. You will need an emulator or the Expo Go App to run the app. The installation of an emulator isn’t covered in this article. Nevertheless, you can check here on how to install an emulator on your computer or the Expo Go app on your mobile device.
Assuming you have an emulator installed, press the relevant key that applies to the emulator, and it’ll run the app on the emulator.
Creating SVG in React Native
We will be creating a custom loader for an application. To start we will need react-native-svg which is a library that provides SVG support for react-native applications. Open a terminal and navigate to the root of your project. Run the code below to install the library
expo install react-native-svg
After installing create a file called Loader.js
in the root directory and paste the code below in the file
import * as React from 'react';
import Svg, { Path } from 'react-native-svg';
const Loader = (props) => (
<Svg width={118} height={107} fill='none' xmlns='http://www.w3.org/2000/svg' {...props}>
<Path
d='M32.333 6C17.608 6 5.667 17.819 5.667 32.4c0 11.77 4.666 39.707 50.602 67.947a5.26 5.26 0 0 0 5.462 0c45.936-28.24 50.602-56.176 50.602-67.947 0-14.581-11.941-26.4-26.666-26.4C70.94 6 59 22 59 22S47.059 6 32.333 6Z'
stroke='#F24E1E'
strokeWidth={10.667}
strokeLinecap='round'
strokeLinejoin='round'
/>
</Svg>
);
export default Loader;
If you’ve used SVG images on the web this should look familiar. The major difference here is we are using the components provided by react-native-svg
for creating our SVG image as opposed to using HTML elements. The react-native-svg
components use sentence case in naming to differentiate from the HTML elements which are lower case.
To render our SVG go to App.js
file and modify it to look like the code below
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View } from 'react-native';
import Loader from './Loader';
export default function App() {
return (
<View style={styles.container}>
<Loader />
<StatusBar style='auto' />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Save, and reload your emulator you should be presented with a screenshot similar to the screenshot below
Converting an existing SVG image to a React native component can be a chore. Luckily there is an open-source tool called SVGR Playground that let’s you generate a React native component from an SVG.
It lets you paste an SVG image on the left and generates a React native SVG component on the right to copy and use. You can go play with it to see how it works.
Open Source Session Replay
OpenReplay is an open-source alternative to FullStory and LogRocket. It gives you full observability by replaying everything your users do on your app and showing how your stack behaves for every issue. OpenReplay is self-hosted for full control over your data.
Happy debugging for modern frontend teams -start monitoring your web app for free.
Adding External SVG to React native applications
The advantage of creating a React native SVG component is that it is customizable. We can pass props and animate as we will see in the next section, but there are times when we just want to use an external SVG image without having to customize it.
There are two ways to achieve this. The react-native-svg
library has a SvgUri
component that allows us to create SVG components from external sources. Create a file called SvgExternal.js
and paste the code below
import * as React from 'react';
import { SvgUri } from 'react-native-svg';
const SvgExternal = (props) => (
<SvgUri width={118} height={107} uri='https://placeholder.pics/svg/118x107/DEDEDE/555555/SVG' {...props} />
);
export default SvgExternal;
It provides a uri
prop that we can pass a link to an external site. Go to the App.js
file and modify the code to display the external SVG.
// previous code
import SvgExternal from './SvgExternal';
export default function App() {
return (
<View style={styles.container}>
<SvgExternal />
<StatusBar style='auto' />
</View>
);
}
// previous code
Now you can open your emulator to view the changes
Another way of achieving this is by using another library called react-native-svg-transformer. It lets you import SVG files into react native projects. Run the code below in your projects terminal to install the library
yarn add --dev react-native-svg-transformer
Create a file called metro.config.js
in your project’s root and paste the code below into it.
const { getDefaultConfig } = require("expo/metro-config");
module.exports = (() => {
const config = getDefaultConfig(__dirname);
const { transformer, resolver } = config;
config.transformer = {
...transformer,
babelTransformerPath: require.resolve("react-native-svg-transformer"),
};
config.resolver = {
...resolver,
assetExts: resolver.assetExts.filter((ext) => ext !== "svg"),
sourceExts: [...resolver.sourceExts, "svg"],
};
return config;
})();
The metro.config.js
is a config file for Metro which is a JavaScript bundler for React native. If you created a react-native project without Expo then paste the code below in your metro.config.js
as the configurations for Expo are different from a bare React native app
const { getDefaultConfig } = require("metro-config");
module.exports = (async () => {
const {
resolver: { sourceExts, assetExts }
} = await getDefaultConfig();
return {
transformer: {
babelTransformerPath: require.resolve("react-native-svg-transformer")
},
resolver: {
assetExts: assetExts.filter(ext => ext !== "svg"),
sourceExts: [...sourceExts, "svg"]
}
};
})();
The next step is getting an SVG file. You can download any on the internet or use this. Move the downloaded file to the assets
directory in your project. Now go to the App.js
file and modify it like the code below to use the file you’ve downloaded.
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, View } from 'react-native';
import PurpleHeart from './assets/purple-heart.svg';
export default function App() {
return (
<View style={styles.container}>
<PurpleHeart />
<StatusBar style='auto' />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Save when you’re done and view the results in your emulator
Animating SVGs in React Native
We’ve so far looked at different ways of adding Svg to react-native. In this section, we will look at how to animate SVG in react-native. We plan to achieve the screenshot below
What we want to do is to change the stroke color of the SVG component every few milliseconds. To get started, create a file called AnimatedLoader.js
and paste the code below. We will be using the React native Animated API to create the animations.
import React, { useEffect, useRef } from 'react';
import { Animated } from 'react-native';
import Svg, { Path } from 'react-native-svg';
const AnimatedPath = Animated.createAnimatedComponent(Path);
const AnimatedLoader = (props) => {
const color = useRef(new Animated.Value(0)).current;
useEffect(() => {
Animated.loop(
Animated.sequence([
Animated.timing(color, { duration: 1000, toValue: 1, useNativeDriver: true }),
Animated.timing(color, { duration: 1000, toValue: 0, useNativeDriver: true }),
])
).start();
}, []);
return (
<Svg width={118} height={107} fill='none' xmlns='http://www.w3.org/2000/svg' {...props}>
<AnimatedPath
d='M32.333 6C17.608 6 5.667 17.819 5.667 32.4c0 11.77 4.666 39.707 50.602 67.947a5.26 5.26 0 0 0 5.462 0c45.936-28.24 50.602-56.176 50.602-67.947 0-14.581-11.941-26.4-26.666-26.4C70.94 6 59 22 59 22S47.059 6 32.333 6Z'
stroke={color.interpolate({
inputRange: [0, 0.2, 0.4, 0.8, 1],
outputRange: [
'rgb(147, 189, 186)',
'rgb(235, 154, 64)',
'rgb(226, 117, 58)',
'rgb(220, 85, 52)',
'rgb(220, 85, 52)',
],
})}
strokeWidth={10.667}
strokeLinecap='round'
strokeLinejoin='round'
/>
</Svg>
);
};
export default AnimatedLoader;
The first thing we’ve done here is to make the Path
component animatable. This allows us to apply animations to the Path
component.
const AnimatedPath = Animated.createAnimatedComponent(Path);
The next step is creating an Animated.Value
that we can attach to an animated component. We used a useRef
hook to store the Animated.Value
so we don’t get to mutate it directly. In the useEffect
hook, we’ve created our animation which is a loop that creates a fade in and fade out effect.
The last thing to do is hook up the animation with the component that needs it. In this case, the AnimatedPath
. We’ve attached the color
Animated.Value
to the stroke
prop of the AnimatedPath
. We’re interpolating the color
Animated Value, what this does is create a color mapping between the inputRange
and outputRange
. Save and reload your emulator to view the changes.
Conclusion
We’ve covered how to use and animate SVG’s in react native. When it comes to animating there is so much more that can be achieved that goes beyond the scope of this article. Endeavor to check the React native Animated API. Animating SVG in React native comes with some performance drawbacks especially for complex animations so endeavor to keep it simple. The code of this article is available here.