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