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