Jahoor! Humanoids heeft een nieuwe website 🎉

SVG's gebruiken in React Native

Ruben Werdmüller
Ruben Werdmüller
Development Team Lead
React code

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.

React Native configureren

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:

npm install react-native-svg

Link de native code voor iOS:

cd ios && pod install && cd ..

SVG als bestand importeren

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:

yarn add --dev react-native-svg-transformer

Vervang of vul je huidige metro.config.js aan in de root van je project met onderstaande configuratie:

// config.metro.js
const { getDefaultConfig } = require("metro-config");
module.exports = () => {
return {
transformer: {
babelTransformerPath: require.resolve("react-native-svg-transformer")
},
resolver: {
assetExts: assetExts.filter(ext => ext !== "svg"),
sourceExts: [...sourceExts, "svg"]
}
};
};

Vervolgens kun je het icoon direct in je code importeren, net als ieder ander React Component:

// app.js
import React from 'react';
import { View, StyleSheet } from 'react-native';
import AwardIcon from './src/assets/icons/award.svg';
const App = () => (
<View style={styles.container}>
<AwardIcon />
</View>
);
const styles = StyleSheet.create({
container: {
alignItems: 'center',
justifyContent: 'center',
flex: 1,
}
});
export default App;

En als resultaat:

Een iphone simulator waarop een trofee in svg formaat is weergegeven.

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.

// award.svg
<svg version="1.1" x="0px" y="0px" viewBox="0 0 512 512"></svg>
<svg></svg>

Het voordeel hiervan is dat je met één bestand een icoon met verschillende formaten en kleuren kan inzetten.

// app.js
const App = () => (
<View style={styles.container}>
<AwardIcon width="100%" height="100%" viewBox="0 0 512 512" fill="tomato"/>
</View>
);

SVGs direct in je code gebruiken

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:

  • De viewBox geven we de afmetingen van de SVG mee om te zorgen dat de inhoud meeschaalt met container.
  • Met de preserveAspectRatio propertie passen we aan hoe de SVG zich verhoudt tot de viewbox. Op MDN is meer te lezen over de toepassing.

// page-divider.js
import React from 'react'
import { View, StyleSheet } from 'react-native'
import Svg, { G, Path } from 'react-native-svg'
export const PageDivider = ({ hasExtraLayer = true, fill = "#4279DD" }) => (
<>
<Svg width="100%" height="320" preserveAspectRatio="xMinYMax" viewBox="0 0 1440 320">
<G {...{ fill }}>
{hasExtraLayer &&
<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" />
}
<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" />
</G>
</Svg >
<View style={styles.container} />
</>
)
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#4279DD",
}
})

En dan krijgen we:

Een iphone simulator waarop een golvende page divider te zien is.

Transformaties toepassen

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:

import React, { useState} from 'react'
import { View, PanResponder } from 'react-native'
import Svg, { Path } from 'react-native-svg'
export const App = () => {
const [lipHeight, setLipHeight] = useState(0)
const responder = PanResponder.create({
onStartShouldSetPanResponder: () => true,
onPanResponderMove: (e, gestureState) => {
setLipsHeight(gestureState.moveY)
},
})
return (
<View {...responder.panHandlers}>
<Svg width="100%" height="100%" >
<Path stroke="#000" strokeWidth="20" strokeLinecap="round" d={`M110,480 Q200,${lipHeight} 300,480`}/>
</Svg >
</View>
)
}

met als resultaat:

Een animatie is een iphone simulator waarop een strakke lijn als het ware naar beneden getrokken wordt met de muis, waardoor het een kromme lijn wordt.

Aan de slag

Tot slot is het een goed idee om deze implementaties zelf ook te draaien om te zien of je alles goed begrijpt. Succes!

Waar kan Humanoids jou bij helpen?

Benieuwd wat we voor je kunnen doen?Geïnteresseerd?