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