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