SVG's gebruiken in React Native
Een eenvoudige opzet voor flexibel gebruik van SVG's
Neem contact op
Een eenvoudige opzet voor flexibel gebruik van SVG's
Op het moment dat je gaat werken met iconen of vector illustraties in een applicatie, ga je willen werken met het Scalable Vector Graphics (SVG) formaat.
Verschillende devices hebben naast een andere grootte scherm, resolutie, ook een andere pixeldichtheid. En in tegenstelling tot .jpeg en .png formaten blijft een SVG altijd scherp, hoe je je iPhone of tablet ook wendt of keert.
Helaas kun je in React (Native) niet standaard een SVG tonen. Terwijl hiervoor in web browsers al even support voor is, moet je voor React Native een pakket downloaden om dit toch voor elkaar te krijgen. Een veel gebruikt pakket hiervoor is react-native-svg.
Voeg react-native-svg toe aan je project:
1npm install react-native-svg
Link de native code voor iOs:
1cd ios && pod install && cd ..
Als je met iconen werkt scheelt het tijd als je deze plug-and-play in je project kan gebruiken. Hiervoor gebruiken we een tweede pakket die dit verzorgt, namelijk: react-native-svg-transformer.
Voeg het pakket toe aan je project:
1yarn add --dev react-native-svg-transformer
Vervang of vul je huidige metro.config.js aan in de root van je project met onderstaande configuratie:
1// config.metro.js
2const { getDefaultConfig } = require("metro-config");
3
4module.exports = () => {
5 return {
6 transformer: {
7 babelTransformerPath: require.resolve("react-native-svg-transformer")
8 },
9 resolver: {
10 assetExts: assetExts.filter(ext => ext !== "svg"),
11 sourceExts: [...sourceExts, "svg"]
12 }
13 };
14};
Vervolgens kun je het icoon direct in je code importeren, net als ieder ander React Component:
1// app.js
2import React from 'react';
3import { View, StyleSheet } from 'react-native';
4
5import AwardIcon from './src/assets/icons/award.svg';
6
7const App = () => (
8 <View style={styles.container}>
9 <AwardIcon />
10 </View>
11);
12
13const styles = StyleSheet.create({
14 container: {
15 alignItems: 'center',
16 justifyContent: 'center',
17 flex: 1,
18 }
19});
20
21export default App;
En als resultaat:
Je kan ook direct properties meegeven. Vergeet niet eventuele properties te verwijderen uit de SVG, inline properties krijgen namelijk voorrang op de properties die worden meegestuurd.
1// award.svg
2<svg version="1.1" x="0px" y="0px" viewBox="0 0 512 512"> … </svg>
3<svg> … </svg>
Het voordeel hiervan is dat je met één bestand een icoon met verschillende formaten en kleuren kan inzetten.
1// app.js
2const App = () => (
3 <View style={styles.container}>
4 <AwardIcon width="100%" height="100%" viewBox="0 0 512 512" fill="tomato"/>
5 </View>
6 );
Wanneer je te maken hebt met complexere toepassingen kan het handig zijn om een SVG op te bouwen met behulp van een functie. Hiermee kun je een section divider met variaties creëren door met booleans delen van de SVG niet te laten zien. Met dit in gedachte gaan we de tool Get Waves gebruiken om een section divider te maken en deze te implementeren op onderstaande wijze. Let daarbij op:
1// page-divider.js
2import React from 'react'
3import { View, StyleSheet } from 'react-native'
4import Svg, { G, Path } from 'react-native-svg'
5
6export const PageDivider = ({ hasExtraLayer = true, fill = "#4279DD" }) => (
7 <>
8 <Svg width="100%" height="320" preserveAspectRatio="xMinYMax" viewBox="0 0 1440 320">
9 <G {...{ fill }}>
10 {hasExtraLayer &&
11 <Path d="M0,128 L288,224 L576,192 L864,160 L1152,320 L1440,288 L1440,320 L1152,320 L864,320 L576,320 L288,320 L0,320Z" />
12 }
13 <Path fillOpacity="0.6" d="M0,128 L80,138.7C160,149,320,171,480,197.3C640,224,800,256,960,266.7 C1120,277, 1280,267, 1360,261.3 L1440,256 L1440,320 L1360,320 C1280,320,1120,320,960,320 C800,320, 640,320, 480,320 C320,320, 160,320, 80,320 L0,320 Z" />
14 </G>
15 </Svg >
16 <View style={styles.container} />
17 </>
18)
19
20const styles = StyleSheet.create({
21 container: {
22 flex: 1,
23 backgroundColor: "#4279DD",
24 }
25})
En dan krijgen we:
SVGs kunnen ook ingezet worden voor illustraties waar interactie een vereiste is. Hiervoor gebruiken we de 'PanResponder' functie van React Native. Deze functie herkent single- en multi-touch gebaren waarmee we kunnen bijhouden waar je het scherm aanraakt.
Dit gaan we gebruiken om een SVG path realtime aan te passen:
1import React, { useState} from 'react'
2import { View, PanResponder } from 'react-native'
3import Svg, { Path } from 'react-native-svg'
4
5export const App = () => {
6 const [lipHeight, setLipHeight] = useState(0)
7
8 const responder = PanResponder.create({
9 onStartShouldSetPanResponder: () => true,
10 onPanResponderMove: (e, gestureState) => {
11 setLipsHeight(gestureState.moveY)
12 },
13 })
14
15 return (
16 <View {...responder.panHandlers}>
17 <Svg width="100%" height="100%" >
18 <Path stroke="#000" strokeWidth="20" strokeLinecap="round" d={`M110,480 Q200,${lipHeight} 300,480`}/>
19 </Svg >
20 </View>
21 )
22}
met als resultaat:
Tot slot is het een goed idee om deze implementaties zelf ook te draaien om te zien of je alles goed begrijpt. Succes!