10

This is my code, I'm trying to load a stream from my IP camera.

  <View style={{flex:1,marginTop:70, flexDirection:'column', justifyContent:'space-between'}}>
    <Hue/>
    <View style={{flex:1}}>
        <WebView
        source={{uri: 'http://192.168.2.6:81/videostream.cgi?user=admin&pwd=XXXXX'}}
        style={{/*marginTop: 20, flex: 1, width:450, height:100*/}}
        javaScriptEnabled={false}
        domStorageEnabled={false}
        startInLoadingState={false}
        scalesPageToFit={false}
        scrollEnabled={true}
        />
    </View>
    <Text>Just some text</Text>

  </View>

<Hue/> is a component to check if the WebView is still loading (because in a normal case, it won't load if it's not the only component).

The width property have an ambiguous behavior: reducing it increase the height of the webview. Leaving an empty scrolling space.

Moreover, modifying the height of the webview component does nothing at all.

I tried to modify the parent view applying height and width with no luck.

Also, I did not find any props to modify the webview content itself.

Is there any way, or a react-native component that can help me to integrate my IP camera stream in my application ?

Any suggestion is very appreciated.

EDIT

Updated the code according to Ashwin's comment and I still get this :

enter image description here

EDIT 2

I updated my code according to sfratini answer but if I set the scroll enabled and then scroll, I'm able so see that there is always a part of the image not displayed. Seems that react does not understand to resize to 100%.. It's strange...

left side

right side

Lawris
  • 965
  • 2
  • 9
  • 21

6 Answers6

11

<WebView
  source={{
    uri: this.props.url
  }}
  style={{ height: height, width, resizeMode: 'cover', flex: 1 }}
  injectedJavaScript={`const meta = document.createElement('meta'); meta.setAttribute('content', 'width=width, initial-scale=0.5, maximum-scale=0.5, user-scalable=2.0'); meta.setAttribute('name', 'viewport'); document.getElementsByTagName('head')[0].appendChild(meta); `}
  scalesPageToFit={false}
  onLoadEnd={this._onLoadEnd}
/>
  • Setting the viewport and scale resolves my problem. Thank you! Without this metadata, the resolution of map I loaded in the webview is very low. – shaosh Aug 17 '20 at 07:37
  • What is the equivalent for `_onLoadEnd` if I use function, not class? – sekrett Mar 22 '21 at 07:10
  • @sekrett anything. Any function. It's just some logic executed after the content is ready. – Jiří Sep 29 '22 at 15:38
3

Managed to get the same behavior for ios and Android. Thanks Gowtham Palanisamy.

<WebView
    source={{ uri: url }}
    style={{ flex: 1 }}
    injectedJavaScript={`
     const iOS = !!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform);
     if (!iOS) {
       const meta = document.createElement('meta');
       let initialScale = 1;
       if(screen.width <= 800) {
        initialScale = ((screen.width / window.innerWidth) + 0.1).toFixed(2);
       }
       const content = 'width=device-width, initial-scale=' + initialScale ;
       meta.setAttribute('name', 'viewport');
       meta.setAttribute('content', content);
       document.getElementsByTagName('head')[0].appendChild(meta);
     }
   `}
    scalesPageToFit={Platform.OS === 'ios'}
  />
Andrey Patseiko
  • 3,687
  • 1
  • 25
  • 24
1

just a note that webview has standard style and also containerStyle see documentation. standard style i believe has background: white, and containerStyle has flex: 1. To make an image responsive, i made my code like this (iframeWidth is just window width dimension minus some padding):

if (node.name === 'img') {
  const imgHeight = Number(node.attribs.height);
  const imgAlt = node.attribs.alt;
  const imgSource = node.attribs.src;
  const imageHtml = `<img src="${imgSource}" height="${
    imgHeight * 2.3
  }" alt="${imgAlt}" />`;
  return (
    <WebView
      key={index}
      source={{ html: imageHtml }}
      startInLoadingState
      scalesPageToFit
      allowsInlineMediaPlayback
      domStorageEnabled
      style={{ backgroundColor: 'transparent' }}
      containerStyle={[{ flex: 0, width: iFrameWidth, height: imgHeight }]}
    />
  );
}

Hope this helps to someone!

verunar
  • 884
  • 12
  • 25
1

Using Gowtham Palanisamy's approach, set the source content as an html input and set its viewport to render content inside parent container.


<View>
  <WebView 
    javaScriptEnabled={false} 
    domStorageEnabled={false} 
    startInLoadingState={false} 
    scalesPageToFit={false} 
    scrollEnabled={true}
    source={{ 
      html: ` 
        <head>
          <meta content="width=width, initial-scale=1, maximum-scale=1" name="viewport"></meta>
        </head>
        <body style="background-image: url('${this.props.source}'); background-size:cover;"></body>
      `, 
    }} 
  />
</View>
1

This is is more better and accurate

style={{ height: 350, width: '100%', resizeMode: 'cover', flex: 1 }}
injectedJavaScript={`const meta = document.createElement('meta'); meta.setAttribute('content', 'width=width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no'); meta.setAttribute('name', 'viewport'); document.getElementsByTagName('head')[0].appendChild(meta); `}
scalesPageToFit={true}
Deepak Panwar
  • 160
  • 10
-3

I believe you want this:

   <WebView 
        source={this.props.source} 
        style={{
            width: '100%',
            height: 300
        }}
        scrollEnabled={false}
        />;
sebastianf182
  • 9,844
  • 3
  • 34
  • 66
  • Thanks for your answer. Unfortunatly, it seems that react don't want to understand the resizing to 100% because the image is not entirely displayed. If I set scrollEnabled to true, I can see that it didn't resized. Please, check my update on my question to see the screenshots. – Lawris Jan 23 '18 at 11:09
  • Isn't that part of the url the webview is loading? What is the source code of that? I am guessing it has a fixed width. – sebastianf182 Jan 23 '18 at 14:17