SVGs in React Native
SVG is amazing like that and preferred implementation on React Native Platform.
How to implement SVGs in RN?
I highly recommend react-native-svg library which provides SVG interface and can help you enhance the visual design of your app in subtle ways that could make a big difference to the look and feel of your app. React-native-svg supports most SVG elements, such as rectangles, circles, lines, paths and more. This library is still growing and new features are being implemented - every new version is better and comes with less bugs.
How to structure SVGs?
Let’s move on to SVG elements structure. Every time you want to place SVG element in your app - you should wrap it using <Svg> component. Without this tag other element's won’t be visible, because vectors need points. Since points are on x and y axes, we have to define our playground in terms of height and width attributes - it works like canvas for us.
ViewBox - our new friend
The viewBox attribute defines the position and dimensions, in user space, of an SVG viewport. The value of the viewBox attribute is a list of four numbers min-x, min-y, width and height, separated by whitespace, which specify a rectangle in user space. This rectangle is mapped to the bounds of the viewport.
We defined our playground - let’s draw some shapes or paths inside. There are several basic shapes used mostly for SVG drawing. The purpose of these shapes can be derived from their names.
SVGs and colors
There are several ways to apply color to these shapes (including specifying attributes on the object) - using inline CSS, an embedded CSS section, or an external CSS file. Most SVGs you'll find around the web use inline CSS. Basic coloring can be done by setting the fill attribute on the node.
Fill sets the color inside the object. In addition, you can specify the opacity of either the fill separately in SVG.
You can also set stroke on the node. Stroke sets the color of the line drawn around the object. Opacity is controlled by the strokeOpacity attribute. There are also additional stroke properties: strokeDasharray which controls the pattern of dashes and gaps and strokeDashoffset which specifies where to start a Dasharray on a line. These two are very useful in animations.
There are also a lot of transformation-related props - and they can be applied either on Group element, or on a single element. Rotation and scale work the same way as the CSS transform property.
The path element - perfect solution
The <path> element is the most powerful element in the SVG library of basic shapes. You can use it to create lines, curves and more. Paths create complex shapes by combining multiple straight lines or curved lines. Complex shapes composed only of straight lines can be created as polylines.
While polylines and paths can create similar-looking shapes, polylines require a lot of small straight lines to simulate curves and don't scale well to larger sizes. A good understanding of paths is important when drawing SVGs. While creating complex paths using text editor is not recommended, understanding how they work will allow you to identify and repair display issues in SVGs.
The shape of a path element is defined by one attribute: d .The "d" attribute contains a series of commands and parameters used by those commands. If you feel that you don’t understand commands like moveTo, lineTo, closePath you can take a look at documentation.
SVG export done seamlessly
Using SVG heavily in an app can degrade its performance, therefore use it with parsimony. And if you do, the app performance will be fine. Now, if you’re working from an original design in Sketch or Illustrator, you won’t be able to simply copy and paste the SVG into your project or export SVG and put to your component. Why? Because properties in original SVG file are dedicated to web implementation, we should always prepare file to implement in React Native. We have to use common props which are specified in react-native-svg library, and for example we don’t need xml property - but no worries things are almost that simple. Of course you can do it manually, but why bother if you can use converters?
Animations - here they come!
I’m a big fan of the Animated API when it comes to animations in React Native. It’s easy to use and powerful, and you can also use it with SVG. To do so, just wrap the native component - you can do this for any SVG component.
The main thing you have to keep in mind is to use setNativeProps instead of using setState in your listener. This makes a native call and bypasses re-calculating the entire component, which in many cases is very complex and slow to do.
Have you ever dreamt of creating your own font?
When it comes to implementing a lot of SVGs, for example icons set, it would be very problematic to add each of them manually. A good practice is to use SVG icons as a font. It’s super simple, all you have to do is to add react-native-vector-icons and react-native-svg libraries to your project and generate font.
You can use apps like icomoon or fontawesome. Export your files, import into collection, generate and Voila! You can download your font now.
In your downloaded folder you can find fonts folder and selection.json file. Add files to your project and link react-native-vector-icons library. It’s almost done. Now you can create Icon component. React-native-vector-icons package has a special function - createIconSetFrom to do it. <Icon> component is ready to use and all you have to know is that this is a normal <Text> element now. Every icon has a name and names are taken from the file name, so when you import files be careful and rename files if it’s necessary.
SVGs - not always a perfect solution
When using SVGs, you have to remember that not everything from SVG is implemented now - filters, gaussian blur or merge are not supported and that means there are not any shadows on SVG elements.
Shadows can be implemented with Linear and RadialGradient. This approach is used in react-native-shadow library, which generates SVG shadows.
Implementing nested Views might be also troublesome. You can put View or TouchableOpacity or whichever Svg element you want, but for some reasons sometimes it won’t be visible. The issue gets more real with more nested Views and more complicated Svg shapes, and paths combination.
ForeignObject, which is used in web implementation is not supported - that means you can’t put JSX inside, but for web you can put HTML. This issue might be confusing, but I think a good practice is to not include JSX inside Svg.
The most annoying issue I have ever encountered is connected with onPress event. It’s highly related to different panResponder behaviour on each Platform. As you can see, there is a lot of closed issues, but sadly, new ones appear very often. My recommendation is to use the newest version of library which contains fixes or using onPressIn event instead of onPress event.
Photo by Frances Gunn on Unsplash