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