2

How to take full page screenshot of webview in react native? Already tried "react-native-view-shot " Link but it only takes screenshot of the visible area. Someone please help. Thanks

Kh An
  • 481
  • 6
  • 13

1 Answers1

2

For future readers: Below is the final script after many attempts, which takes full page screenshot from Webview. I have used ProgressWebView instead of Webview. You can use Webview if you want. This code works in functional components. Note: When the page is fully loaded then click on the Take Screenshot button

import React, { useState } from 'react';
import { View, Button } from 'react-native';
import { captureRef } from "react-native-view-shot";
import ProgressWebView from "react-native-progress-webview";
import json5 from 'json5'
import { Dimensions } from 'react-native';

const Report = () => {
   const [componentHeight, setComponentHeight] = useState(0)
   const [globalComponentHeight, setGlobalComponentHeight] = useState(0)
   const [componentHeightFlex, setComponentHeightFlex] = useState(1)
   let url = 'https://stackoverflow.com/questions/63708244/webview-full-page-screenshot-in-react-native'
   let webview = null;
   let count = 0
   const injectJS =  _ => {
       const script = `
         let method${count} = _ => {
         let documentHeight = document.body.scrollHeight
         let data = {componentHeight: documentHeight}
         window.ReactNativeWebView.postMessage(JSON.stringify(data))
     }
     method${count}()`
  webview.injectJavaScript(script)
  count++
}
const takeScreenshot = _ => {
  console.log(globalComponentHeight)
  const {height} = Dimensions.get("window")
  console.log(height)
  if(globalComponentHeight <= height) setComponentHeight(height)
  else setComponentHeight(globalComponentHeight)
  setComponentHeightFlex(null)
  setTimeout(_ => {
     captureRef(webview, {
        format: "png",
        quality: 0.9,
        result: "base64"
     }).then(
        _screenshot => {
          console.log(_screenshot)
           //First save your screenshot from _screenshot(base64 string). You can send base64 string to your server and save
           //Then make the component default as below
           setComponentHeight(0)
           setComponentHeightFlex(1)
        },
        error => console.error("Oops, screenshot failed", error)
     );
  }, 100)
}
return (
  <View style={{ marginTop: 40, flex: 1, display: 'flex' }}>
     <Button mode='contained' onPress={takeScreenshot} title="Take Screenshot"/>
     <View
        style={{
           height: componentHeight,
           flex: componentHeightFlex
        }}
     >
        <ProgressWebView
           ref={ref => {
              if (ref != null)
                 webview = ref
           }}
           bounces={false}
           style={{ position: 'relative' }}
           showsHorizontalScrollIndicator={false}
           showsVerticalScrollIndicator={true}
           source={{ uri: url }}
           startInLoadingState={true}
           onLoad={e => injectJS()}
           onMessage={e => {
              let data = json5.parse(e.nativeEvent.data)
              // console.log(data)
              setGlobalComponentHeight(parseInt(data.componentHeight))
           }}
        ></ProgressWebView>
     </View>
  </View>
);
}
export default Report
Kh An
  • 481
  • 6
  • 13
  • Neither progressive web view nor a webview is a React component though, so the call fails. Only workaround that comes to my mind is to set the ref to the parent View, but that takes us back to capturing only the visible content, not the entire page. Any ideas? – DanDayne Mar 23 '23 at 23:31