1---
2title: Handle platform differences
3---
4
5import { SnackInline, Terminal } from '~/ui/components/Snippet';
6import Video from '~/components/plugins/Video';
7import { A } from '~/ui/components/Text';
8import { Step } from '~/ui/components/Step';
9
10Android, iOS, and the web have different capabilities. In our case, Android and iOS both are able to capture a screenshot with the `react-native-view-shot` library, however web browsers cannot.
11
12In this chapter, let's learn how to make an exception for web browsers to get the same functionality on all platforms.
13
14<Step label="1">
15
16## Install and import dom-to-image
17
18To capture a screenshot on the web and save it as an image , we'll use a third-party library called [dom-to-image](https://github.com/tsayen/dom-to-image#readme).
19It allows taking a screenshot of any DOM node and turning it into a vector (SVG) or raster (PNG or JPEG) image.
20
21Stop the development server and run the following command to install the library:
22
23<Terminal cmd={['$ npm install dom-to-image']} />
24
25After installing it, make sure to restart the development server and press <kbd>w</kbd> in the terminal.
26
27To use it, let's import it into **App.js**:
28
29```jsx App.js
30import domtoimage from 'dom-to-image';
31```
32
33</Step>
34
35<Step label="2">
36
37## Add platform-specific code
38
39React Native provides a `Platform` module that gives us access to information about the platform on which the app is currently running.
40You can use it to implement platform-specific behavior.
41
42Import the `Platform` module in **App.js**:
43
44{/* prettier-ignore */}
45```jsx App.js
46import { StyleSheet, View, /* @info Import the Platform module from react-native. */ Platform /* @end */ } from 'react-native';
47```
48
49Inside the `onSaveImageAsync()` function in the `<App>` component, we'll use `Platform.OS` to check whether the platform is `'web'`.
50If it is not `'web'`, we'll run the logic added previously to take and save the screenshot. If it is `'web'`,
51we'll use the `domtoimage.toJpeg()` method to convert and capture the current `<View>` as a JPEG image.
52
53<SnackInline
54label="Take a screenshot"
55templateId="tutorial/08-run-on-web/App"
56dependencies={['expo-image-picker', '@expo/vector-icons/FontAwesome', '@expo/vector-icons', 'expo-status-bar', '@expo/vector-icons/MaterialIcons', 'react-native-gesture-handler', 'react-native-reanimated', 'react-native-view-shot', 'expo-media-library', '[email protected]']}
57files={{
58  'assets/images/background-image.png': 'https://snack-code-uploads.s3.us-west-1.amazonaws.com/~asset/503001f14bb7b8fe48a4e318ad07e910',
59  'assets/images/emoji1.png': 'https://snack-code-uploads.s3.us-west-1.amazonaws.com/~asset/be9751678c0b3f9c6bf55f60de815d30',
60  'assets/images/emoji2.png': 'https://snack-code-uploads.s3.us-west-1.amazonaws.com/~asset/7c0d14b79e134d528c5e0801699d6ccf',
61  'assets/images/emoji3.png': 'https://snack-code-uploads.s3.us-west-1.amazonaws.com/~asset/d713e2de164764c2ab3db0ab4e40c577',
62  'assets/images/emoji4.png': 'https://snack-code-uploads.s3.us-west-1.amazonaws.com/~asset/ac2163b98a973cb50bfb716cc4438f9a',
63  'assets/images/emoji5.png': 'https://snack-code-uploads.s3.us-west-1.amazonaws.com/~asset/9cc0e2ff664bae3af766b9750331c3ad',
64  'assets/images/emoji6.png': 'https://snack-code-uploads.s3.us-west-1.amazonaws.com/~asset/ce614cf0928157b3f7daa3cb8e7bd486',
65  'components/ImageViewer.js': 'tutorial/02-image-picker/ImageViewer.js',
66  'components/Button.js': 'tutorial/03-button-options/Button.js',
67  'components/CircleButton.js': 'tutorial/03-button-options/CircleButton.js',
68  'components/IconButton.js': 'tutorial/03-button-options/IconButton.js',
69  'components/EmojiPicker.js': 'tutorial/04-modal/EmojiPicker.js',
70  'components/EmojiList.js': 'tutorial/05-emoji-list/EmojiList.js',
71  'components/EmojiSticker.js': 'tutorial/06-gestures/CompleteEmojiSticker.js',
72}}>
73
74{/* prettier-ignore */}
75```jsx
76const onSaveImageAsync = async () => {
77  /* @info Add the if condition here to check whether the current platform is web or not. */ if (Platform.OS !== 'web') { /* @end */
78    try {
79      const localUri = await captureRef(imageRef, {
80        height: 440,
81        quality: 1,
82      });
83      await MediaLibrary.saveToLibraryAsync(localUri);
84      if (localUri) {
85        alert('Saved!');
86      }
87    } catch (e) {
88      console.log(e);
89    }
90  } /* @info Add an else condition to run the logic when the current platform is the web. */else {
91    domtoimage
92      .toJpeg(imageRef.current, {
93          quality: 0.95,
94          width: 320,
95          height: 440,
96        })
97      .then(dataUrl => {
98        let link = document.createElement('a');
99        link.download = 'sticker-smash.jpeg';
100        link.href = dataUrl;
101        link.click();
102      })
103      .catch(e => {
104        console.log(e);
105      });
106  } /* @end */
107};
108```
109
110</SnackInline>
111
112On running the app in a web browser, we can now save a screenshot:
113
114<Video file="tutorial/web.mp4" />
115
116</Step>
117
118## Next steps
119
120The app does everything we set out for it to do, so it's time to shift our focus towards the purely aesthetic.
121In the next chapter, we will [customize the app's status bar, splash screen, and app icon](/tutorial/configuration).
122