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## Up next
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