Giter VIP home page Giter VIP logo

gre / react-native-view-shot Goto Github PK

View Code? Open in Web Editor NEW
2.6K 2.6K 334.0 6.8 MB

Snapshot a React Native view and save it to an image

Home Page: https://github.com/gre/react-native-view-shot-example

License: MIT License

Java 35.12% JavaScript 39.87% Objective-C 6.57% C# 7.04% Ruby 1.34% Starlark 0.44% Makefile 1.12% C++ 5.14% Objective-C++ 2.69% EJS 0.40% TypeScript 0.27%
capture react-native snapshot

react-native-view-shot's Introduction

react-native-view-shot

Capture a React Native view to an image.

Install

yarn add react-native-view-shot

# In Expo

expo install react-native-view-shot

Make sure react-native-view-shot is correctly linked in Xcode (might require a manual installation, refer to React Native doc).

Before React Native 0.60.x you would have to:

react-native link react-native-view-shot

Since 0.60.x, autolink should just work, on iOS, you'll need to ensure the CocoaPods are installed with:

npx pod-install

High Level API

import ViewShot from "react-native-view-shot";

function ExampleCaptureOnMountManually {
  const ref = useRef();

  useEffect(() => {
    // on mount
    ref.current.capture().then(uri => {
      console.log("do something with ", uri);
    });
  }, []);

  return (
    <ViewShot ref={ref} options={{ fileName: "Your-File-Name", format: "jpg", quality: 0.9 }}>
      <Text>...Something to rasterize...</Text>
    </ViewShot>
  );
}

// alternative
function ExampleCaptureOnMountSimpler {
  const ref = useRef();

  const onCapture = useCallback(uri => {
    console.log("do something with ", uri);
  }, []);

  return (
    <ViewShot onCapture={onCapture} captureMode="mount">
      <Text>...Something to rasterize...</Text>
    </ViewShot>
  );
}

// waiting an image

function ExampleWaitingCapture {
  const ref = useRef();

  const onImageLoad = useCallback(() => {
    ref.current.capture().then(uri => {
      console.log("do something with ", uri);
    })
  }, []);

  return (
    <ViewShot ref={ref}>
      <Text>...Something to rasterize...</Text>
      <Image ... onLoad={onImageLoad} />
    </ViewShot>
  );
}

// capture ScrollView content
// NB: you may need to go the "imperative way" to use snapshotContentContainer with the scrollview ref instead
function ExampleCaptureOnMountSimpler {
  const ref = useRef();

  const onCapture = useCallback(uri => {
    console.log("do something with ", uri);
  }, []);

  return (
    <ScrollView>
      <ViewShot onCapture={onCapture} captureMode="mount">
        <Text>...The Scroll View Content Goes Here...</Text>
      </ViewShot>
    </ScrollView>
  );
}

Props:

  • children: the actual content to rasterize.
  • options: the same options as in captureRef method.
  • captureMode (string):
    • if not defined (default). the capture is not automatic and you need to use the ref and call capture() yourself.
    • "mount". Capture the view once at mount. (It is important to understand image loading won't be waited, in such case you want to use "none" with viewShotRef.capture() after Image#onLoad.)
    • "continuous" EXPERIMENTAL, this will capture A LOT of images continuously. For very specific use-cases.
    • "update" EXPERIMENTAL, this will capture images each time React redraw (on did update). For very specific use-cases.
  • onCapture: when a captureMode is defined, this callback will be called with the capture result.
  • onCaptureFailure: when a captureMode is defined, this callback will be called when a capture fails.

captureRef(view, options) lower level imperative API

import { captureRef } from "react-native-view-shot";

captureRef(viewRef, {
  format: "jpg",
  quality: 0.8,
}).then(
  (uri) => console.log("Image saved to", uri),
  (error) => console.error("Oops, snapshot failed", error)
);

Returns a Promise of the image URI.

  • view is a reference to a React Native component.
  • options may include:
    • fileName (string): (Android only) the file name of the file. Must be at least 3 characters long.
    • width / height (number): the width and height of the final image (resized from the View bound. don't provide it if you want the original pixel size).
    • format (string): either png or jpg or webm (Android). Defaults to png.
    • quality (number): the quality. 0.0 - 1.0 (default). (only available on lossy formats like jpg)
    • result (string), the method you want to use to save the snapshot, one of:
      • "tmpfile" (default): save to a temporary file (that will only exist for as long as the app is running).
      • "base64": encode as base64 and returns the raw string. Use only with small images as this may result of lags (the string is sent over the bridge). N.B. This is not a data uri, use data-uri instead.
      • "data-uri": same as base64 but also includes the Data URI scheme header.
    • snapshotContentContainer (bool): if true and when view is a ScrollView, the "content container" height will be evaluated instead of the container height.
    • [iOS] useRenderInContext (bool): change the iOS snapshot strategy to use method renderInContext instead of drawViewHierarchyInRect which may help for some use cases.

releaseCapture(uri)

This method release a previously captured uri. For tmpfile it will clean them out, for other result types it just won't do anything.

NB: the tmpfile captures are automatically cleaned out after the app closes, so you might not have to worry about this unless advanced usecases. The ViewShot component will use it each time you capture more than once (useful for continuous capture to not leak files).

captureScreen() Android and iOS Only

import { captureScreen } from "react-native-view-shot";

captureScreen({
  format: "jpg",
  quality: 0.8,
}).then(
  (uri) => console.log("Image saved to", uri),
  (error) => console.error("Oops, snapshot failed", error)
);

This method will capture the contents of the currently displayed screen as a native hardware screenshot. It does not require a ref input, as it does not work at the view level. This means that ScrollViews will not be captured in their entirety - only the portions currently visible to the user.

Returns a Promise of the image URI.

  • options: the same options as in captureRef method.

Advanced Examples

Checkout react-native-view-shot-example

Interoperability Table

Snapshots are not guaranteed to be pixel perfect. It also depends on the platform. Here is some difference we have noticed and how to workaround.

Model tested: iPhone 6 (iOS), Nexus 5 (Android).

System iOS Android Windows
View,Text,Image,.. YES YES YES
WebView YES YES1 YES
gl-react v2 YES NO2 NO3
react-native-video NO NO NO
react-native-maps YES NO4 NO3
react-native-svg YES YES maybe?
react-native-camera   NO               YES               NO 3       
  1. Only supported by wrapping a <View collapsable={false}> parent and snapshotting it.
  2. It returns an empty image (not a failure Promise).
  3. Component itself lacks platform support.
  4. But you can just use the react-native-maps snapshot function: https://github.com/airbnb/react-native-maps#take-snapshot-of-map

Performance Optimization

During profiling captured several things that influence on performance:

  1. (de-)allocation of memory for bitmap
  2. (de-)allocation of memory for Base64 output buffer
  3. compression of bitmap to different image formats: PNG, JPG

To solve that in code introduced several new approaches:

  • reusable images, that reduce load on GC;
  • reusable arrays/buffers that also reduce load on GC;
  • RAW image format for avoiding expensive compression;
  • ZIP deflate compression for RAW data, that works faster in compare to Bitmap.compress

more details and code snippet are below.

RAW Images

Introduced a new image format RAW. it correspond a ARGB array of pixels.

Advantages:

  • no compression, so its supper quick. Screenshot taking is less than 16ms;

RAW format supported for zip-base64, base64 and tmpfile result types.

RAW file on disk saved in format: ${width}:${height}|${base64} string.

zip-base64

In compare to BASE64 result string this format fast try to apply zip/deflate compression on screenshot results and only after that convert results to base64 string. In combination zip-base64 + raw we got a super fast approach for capturing screen views and deliver them to the react side.

How to work with zip-base64 and RAW format?

const fs = require("fs");
const zlib = require("zlib");
const PNG = require("pngjs").PNG;
const Buffer = require("buffer").Buffer;

const format = Platform.OS === "android" ? "raw" : "png";
const result = Platform.OS === "android" ? "zip-base64" : "base64";

captureRef(this.ref, { result, format }).then((data) => {
  // expected pattern 'width:height|', example: '1080:1731|'
  const resolution = /^(\d+):(\d+)\|/g.exec(data);
  const width = (resolution || ["", 0, 0])[1];
  const height = (resolution || ["", 0, 0])[2];
  const base64 = data.substr((resolution || [""])[0].length || 0);

  // convert from base64 to Buffer
  const buffer = Buffer.from(base64, "base64");
  // un-compress data
  const inflated = zlib.inflateSync(buffer);
  // compose PNG
  const png = new PNG({ width, height });
  png.data = inflated;
  const pngData = PNG.sync.write(png);
  // save composed PNG
  fs.writeFileSync(output, pngData);
});

Keep in mind that packaging PNG data is a CPU consuming operation as a zlib.inflate.

Hint: use process.fork() approach for converting raw data into PNGs.

Note: code is tested in large commercial project.

Note #2: Don't forget to add packages into your project:

yarn add pngjs
yarn add zlib

Troubleshooting / FAQ

Saving to a file?

The snapshot is rejected with an error?

  • Support of special components like Video / GL views is not guaranteed to work. In case of failure, the captureRef promise gets rejected (the library won't crash).

get a black or blank result or still have an error with simple views?

Check the Interoperability Table above. Some special components are unfortunately not supported. If you have a View that contains one of an unsupported component, the whole snapshot might be compromised as well.

black background instead of transparency / weird border appear around texts?

  • It's preferable to use a background color on the view you rasterize to avoid transparent pixels and potential weirdness that some border appear around texts.

on Android, getting "Trying to resolve view with tag '{tagID}' which doesn't exist"

you need to make sure collapsable is set to false if you want to snapshot a View. Some content might even need to be wrapped into such <View collapsable={false}> to actually make them snapshotable! Otherwise that view won't reflect any UI View. (found by @gaguirre)

Alternatively, you can use the ViewShot component that will have collapsable={false} set to solve this problem.

Getting "The content size must not be zero or negative."

Make sure you don't snapshot instantly, you need to wait at least there is a first onLayout event, or after a timeout, otherwise the View might not be ready yet. (It should also be safe to just wait Image onLoad if you have one). If you still have the problem, make sure your view actually have a width and height > 0.

Alternatively, you can use the ViewShot component that will wait the first onLayout.

Snapshotted image does not match my width and height but is twice/3-times bigger

This is because the snapshot image result is in real pixel size where the width/height defined in a React Native style are defined in "point" unit. You might want to set width and height option to force a resize. (might affect image quality)

on Android, capture GL Views

A prop may be necessary to properly capture GL Surface View in the view tree:

/**
  * if true and when view is a SurfaceView or have it in the view tree, view will be captured.
  * False by default, because it can have signoficant performance impact
  */
handleGLSurfaceViewOnAndroid?: boolean;

Trying to share the capture result with expo-sharing?

tmpfile or the default capture result works best for this. Just be sure to prepend file:// to result before you call shareAsync.

captureRef(viewRef)
  .then((uri) => Sharing.shareAsync(`file://${uri}`, options)

Thanks

react-native-view-shot's People

Contributors

acrazing avatar ardavank avatar avioli avatar bardolos avatar brentvatne avatar cortinico avatar dependabot[bot] avatar foxmicha avatar gaykov avatar gre avatar henleykuang avatar jeremygreen-tomtom avatar lekenny avatar lionelwei avatar lkyyuen avatar pietropizzi avatar qmatteoq avatar qrymy avatar ryanlntn avatar seanmclem avatar sjchmiela avatar skellock avatar stevepotter avatar systemride avatar taym95 avatar therogue76 avatar vcalvello avatar vmbindraban avatar wassgha avatar wazzez avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-native-view-shot's Issues

Cannot take snapshot in real Device, but simulator is fine

Hi, I would like to capture my WebView. In the simulator, it works fine, and I can store it to any Dir. However, when I run the code using debug mode or release mode on my device, it always shows the same error. Could you please point out what's wrong here? Thanks.

Here is the error message:

2017-03-07 11:33:35.413 [info][tid:com.facebook.react.JavaScript] { [Error: Failed to capture view snapshot]
  line: 2813,
  column: 24,
  sourceURL: 'file:///var/containers/Bundle/Application/F030ED8C-8964-4991-91A6-6A5AFDFC23A5/Altizure.app/main.jsbundle',
  framesToPop: 1,
  code: 'EUNSPECIFIED',
  nativeStackIOS: 
   [ '0   Altizure                            0x00000001001e0634 RCTJSErrorFromCodeMessageAndNSError + 152',
     '1   Altizure                            0x000000010016a1b4 __41-[RCTModuleMethod processMethodSignature]_block_invoke_2.224 + 184',
     '2   Altizure                            0x00000001003a8b74 __54-[RNViewShot takeSnapshot:withOptions:resolve:reject:]_block_invoke + 988',
     '3   Altizure                            0x000000010021c78c __29-[RCTUIManager flushUIBlocks]_block_invoke + 660',
     '4   libdispatch.dylib                   0x00000001008d9258 _dispatch_call_block_and_release + 24',
     '5   libdispatch.dylib                   0x00000001008d9218 _dispatch_client_callout + 16',
     '6   libdispatch.dylib                   0x00000001008de280 _dispatch_main_queue_callback_4CF + 1200',
     '7   CoreFoundation                      0x000000018c2aa810 <redacted> + 12',
     '8   CoreFoundation                      0x000000018c2a83fc <redacted> + 1660',
     '9   CoreFoundation                      0x000000018c1d62b8 CFRunLoopRunSpecific + 444',
     '10  GraphicsServices                    0x000000018dc8a198 GSEventRunModal + 180',
     '11  UIKit                               0x000000019221d7fc <redacted> + 684',
     '12  UIKit                               0x0000000192218534 UIApplicationMain + 208',
     '13  Altizure                            0x00000001000fa144 main + 124',
     '14  libdyld.dylib                       0x000000018b1b95b8 <redacted> + 4' ],
  domain: 'RCTErrorDomain',
  userInfo: null }

Development environment:
Xcode 8.2.1
iOS 10.2
ReactNative 0.42

To reproduce:

async takeSnapshot() {
        try {
            this.snapshot = await takeSnapshot(this.modelContainer, {
                format: "jpeg",
                quality: 0.7,
                path: PictureDir + "/snapshot.jpeg"
            });
            console.log(this.snapshot);
        } catch (err) {
            console.log(err);
        }
    }
<View style={styles.viewer} ref={(ref) => { this.modelContainer = ref; }}>
     <WkWebView
          ref={(ref) => { this.webview = ref; }}
          startInLoadingState={true}
          renderLoading={this.renderLoading}
          source={require('./earth.html')}
          onMessage={(event) => this.shareSheet.earth(event.body, this.snapshot)}
          injectedJavaScript={jsCode}
          javaScriptEnabled={true}
    />
</View>
viewer: {
    flex: 1,
    zIndex: -1,
    backgroundColor: '#232323'
}

Custom width height of snapshot

How can I custom size of Image file after take snapshot? I tested on iPhone 6 simulator, file result only have 750px width.

Example: I wanna result file have 2048x2048 px.

persistent storage...

instead of writing into tmp file,,why don't store image into persistent storage such as Documents directory..?? after that image can be accessed with ~/Documents/filename...

Detect snap

Is there a any way for detect user manual snapshot ?

Support for ReactNativeART?

Hi,
Thanks for this good plugin.

Is there any way for this plugin to support the ReactNativeART library? Or do you have any plans to add this feature?

I would love to use it with a components like Surface, Shape, Path from ReactNativeART.

Thanks for advance.

could i ask ,how to specifyc img base dir

if i want to specifyc img to path "file:///storage/emulated/0/Tencent/MicroMsg/WeiXin",
i tryed to write like
`path:"file:///storage/emulated/0/Tencent/MicroMsg/WeiXin/qr.png" but failed ,

error save: ReferenceError: file is not defined?

I did your example but it always throw the error

error save:  ReferenceError: file is not defined
    at http://localhost:8081/index.ios.bundle?platform=ios&dev=true&minify=false:78636:31
    at tryCallOne (http://localhost:8081/index.ios.bundle?platform=ios&dev=true&minify=false:32137:8)
    at http://localhost:8081/index.ios.bundle?platform=ios&dev=true&minify=false:32223:9
    at http://localhost:8081/index.ios.bundle?platform=ios&dev=true&minify=false:5651:49
    at Object.callTimer (http://localhost:8081/index.ios.bundle?platform=ios&dev=true&minify=false:4156:1)
    at Object.callImmediatesPass (http://localhost:8081/index.ios.bundle?platform=ios&dev=true&minify=false:4260:19)
    at Object.callImmediates (http://localhost:8081/index.ios.bundle?platform=ios&dev=true&minify=false:4275:25)
    at http://localhost:8081/index.ios.bundle?platform=ios&dev=true&minify=false:3962:43
    at guard (http://localhost:8081/index.ios.bundle?platform=ios&dev=true&minify=false:3794:1)
    at MessageQueue.__callImmediates (http://localhost:8081/index.ios.bundle?platform=ios&dev=true&minify=false:3962:1)

My code

  snapshot = refname => () => {
    console.log(refname)
      RNViewShot.takeSnapshot(this.refs[refname], {format: "jpeg", quality: 0.8, result: "file"})
          .then(
              uri => {
                  console.log("Image saved to ", file);
              }
          )
          .catch(error => console.log('error save: ', error));
  }

save as base64 throw error

when i save image as base64, throw a error, and set result to 'data-uri' is same.

RN version: 0.36.1.

code:
RNViewShot.takeSnapshot(this.ref, { format: "png", quality: 0.8, result: 'base64', })

error:

'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[0]'
*** First throw call stack:
(
0 CoreFoundation 0x0000000106df8d85 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010642bdeb objc_exception_throw + 48
2 CoreFoundation 0x0000000106cb1a52 -[__NSPlaceholderArray initWithObjects:count:] + 290
3 CoreFoundation 0x0000000106d0e0b4 +[NSArray arrayWithObjects:count:] + 52
4 mofang_app 0x0000000102908edf -[RCTPhotoLibraryImageLoader loadImageForURL:size:scale:resizeMode:progressHandler:partialLoadHandler:completionHandler:] + 447
5 mofang_app 0x0000000102a155d3 __118-[RCTImageLoader _loadImageOrDataWithURLRequest:size:scale:resizeMode:progressBlock:partialLoadBlock:completionBlock:]_block_invoke.191 + 355
6 libdispatch.dylib 0x0000000107edbd9d _dispatch_call_block_and_release + 12
7 libdispatch.dylib 0x0000000107efc3eb _dispatch_client_callout + 8
8 libdispatch.dylib 0x0000000107ee282c _dispatch_queue_drain + 2215
9 libdispatch.dylib 0x0000000107ee1d4d _dispatch_queue_invoke + 601
10 libdispatch.dylib 0x0000000107ee4996 _dispatch_root_queue_drain + 1420
11 libdispatch.dylib 0x0000000107ee4405 _dispatch_worker_thread3 + 111
12 libsystem_pthread.dylib 0x00000001082394de _pthread_wqthread + 1129
13 libsystem_pthread.dylib 0x0000000108237341 start_wqthread + 13
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)

A few Questions

Hi there, first thing thanks very much for your hard work on this project :)

I would like to know if there is a way to take a snapshot without passing the ref, and i'm asking this because to get the ref (correct me if i'm wrong) you need to render the element, and that's my problem, i have to create images of about 80 views. as you understand this is a performance killer.

If you believe it's possible to make this in some way.
i'm very interesting to know your toughs's on this one.

in the native code side i was think something like this:
Pass to bridge Component and props-->In the Native side call react-native method to create the View in the background--> create a image of the view --> return path

All this procedure made with multi threading support.

Attention, i never create a native module for react-native, it's probably that i said something stupid above.

This issue is to know if Its possible to do, if you can do it, and if you can't , if you could assist me to do it.

Captured view not seen any more

Hi,

I successfully capture the view as png/jpeg in react-native in Android.

I captured the view as file and saved for later use. The view contain image and text. But the original view in the screen disappeared (become empty in the screen) after captured the view.

I want to display the same view (not captured image) even after captured the image. Any way to achieve this ? Please advise ASAP.

Please find attached the before view and after captured view (empty).

error-before
error-after

Render off screen area

Hi,

is it possible to capture a whole View, even the parts that are not yet on screen (like in a scrollview)?
Or even better: capture a View that has not yet been given to the render method?
e.g.

createView(){ 
		return <View>
			<Text>Hello World</Text>
		</View>
	}
...
RNViewShot.takeSnapshot(this.createView(), {
					 format: 'png',
					result: 'file',
					 });

Is this planned, and would this at all be possible with the current architecture?
Best, Tim

Blur image

The shot image is blur, even though I set the quality to 1.0.
Is there anyway to get a high quality or clear image?

[Android] Sharing the generated image with a share intent

Hi, maybe this is more a general purpose Android question, but I thought perhaps you could help. Since the uri that is generated for a snapshot only exists in the app cache, passing its uri to a share intent always fails. As soon as I change it to a file saved on external storage, it works. Obviously I'd like to avoid doing this, so I'm looking for other ways to achieve this. More than willing to submit a PR. Thanks!

EDIT: My proposal would be an option like {saveToDisk: true} being passed in which would cause the module to call something like createPermanentFile instead of createTempFile, but my native Android fu is limited, so there's probably a better way.

Image real path to save it to camera roll

I was tried the example code and i got a uri like this:
file:///data/user/0/com.last/cache/ReactNative-snapshot-image1446502249.png

Is there any way to change the uri into the real path? just like:
"/storage/emulated/0/Pictures/ReactNative-snapshot-image799473449.png"

so i could use the path for the CameraRoll library from react native like:
CameraRoll.saveToCameraRoll(path,'photo')

Thanks and please help hehe

Rejecting while taking snapshot of "zero height" view

I got following error/rejection:

2016-11-12 13:43:43.339 [info][tid:com.facebook.react.JavaScript] 'Taking snapshot', true
Nov 12 13:43:43  rnSnapshooter[96767] <Error>: CGContextSaveGState: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
Nov 12 13:43:43  rnSnapshooter[96767] <Error>: CGContextRestoreGState: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
2016-11-12 13:43:43.380 [error][tid:com.facebook.react.JavaScript] 'Oops, snapshot failed', { [Error: Failed to capture view snapshot]
  line: 3548,
  column: 20,
  sourceURL: 'http://localhost:8081/index.ios.bundle?platform=ios&dev=true&minify=false',
  framesToPop: 1,
  code: 'EUNSPECIFIED',
  nativeStackIOS: 
   [ '0   rnSnapshooter                       0x000000010a054ea6 RCTJSErrorFromCodeMessageAndNSError + 134',
     '1   rnSnapshooter                       0x0000000109fd4aa3 __41-[RCTModuleMethod processMethodSignature]_block_invoke_2.224 + 147',
     '2   rnSnapshooter                       0x000000010a0fb899 __54-[RNViewShot takeSnapshot:withOptions:resolve:reject:]_block_invoke + 1161',
     '3   rnSnapshooter                       0x000000010a08f4d8 __29-[RCTUIManager flushUIBlocks]_block_invoke + 792',
     '4   libdispatch.dylib                   0x000000010e57fe5d _dispatch_call_block_and_release + 12',
     '5   libdispatch.dylib                   0x000000010e5a049b _dispatch_client_callout + 8',
     '6   libdispatch.dylib                   0x000000010e5882af _dispatch_main_queue_callback_4CF + 1738',
     '7   CoreFoundation                      0x000000010b59bd09 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9',
     '8   CoreFoundation                      0x000000010b55d2c9 __CFRunLoopRun + 2073',
     '9   CoreFoundation                      0x000000010b55c828 CFRunLoopRunSpecific + 488',
     '10  GraphicsServices                    0x000000011003cad2 GSEventRunModal + 161',
     '11  UIKit                               0x000000010cf59610 UIApplicationMain + 171',
     '12  rnSnapshooter                       0x0000000109fac8bf main + 111',
     '13  libdyld.dylib                       0x000000010e5d492d start + 1' ],
  domain: 'RCTErrorDomain',
  userInfo: null }

with following view to snapshot:

      <View ref="root" style={{backgroundColor: 'yellow'}}>
        <DemoApp/>
      </View>

everything works with style={{flex:1,backgroundColor: 'yellow'}}. Without the flex I can see DemoApp but I don't see yellow background.

Feel free to close this issue if you don't want to handle such cases. Just wanted to document somewhere my troubles and how to "workaround" them if anyone would come to this problem.

React Native Version

Im on RN 0.27.2 and I got it working just great with IOS, However android fails with import com.facebook.react.uimanager.UIBlock; and anything that uses the UIBlock, Does android only work with versions of react-native that are react-native@>=0.30.0?

Error: findNodeHandle failed to resolve view=undefined

Hi
I integrated rnvs few weeks back and it was working perfectly then. Suddenly I am seeing error whenever I am trying to capture screenshot.
Here is my code for taking screenshot.

takeScreenShot(){
    RNViewShot.takeSnapshot(this.refs.screenshot, {
      format: "jpeg",
      quality: 0.8
    })
    .then(
      uri => this.saveScreenshot(uri),
      error => console.error("Oops, snapshot failed", error)
    );
  }

This is the error I am getting whenever calling takeScreenShot function.

2016-12-06 14:34:22.635 [error][tid:com.facebook.react.JavaScript] 'Oops, snapshot failed', { [Error: findNodeHandle failed to resolve view=undefined]
line: 525,
column: 133,
sourceURL: 'file:///Users/ABC/Library/Developer/CoreSimulator/Devices/17A973BC-5639-4C55-B52E-D7FE972F2651/data/Containers/Bundle/Application/87DDE253-950F-4BB2-8F4C-C8C468862DD2/MYAPP.app/main.jsbundle' }

Exporting airbnb/react-native-map results in blank image

Hello first of all great package 😄 .

This is more a question than an issue, but trying to export a MapView from https://github.com/airbnb/react-native-maps the map itself is a blank. Do you have any idea on why this could be happening?. Could it be that is probably a native element so this exporter does not know how to render something that is not a react-native rendered element? (I imagine i can be completely wrong on my self-explanation on why it does not work)

[Question] On ScrollView, how to take picture all of it, not only visible part?

Hi, I have a long page which user have to scroll down to read all of it. This page is something user want to share on social media, so I need to take a shot whole scrollview content.
So, I've tried to use this package to take the image but it only returns what's visible on screen at the moment, I've also tried snapshotContentContainer option but no luck so far.

Can't get Image to show

This is what i get when running my script:
"file:///data/user/0/com.coach/cache/ReactNative-snapshot-image1317300113.png"

When i put it like this:
<Image source={{uri: uriAbove }} />
it shows nothing.

When i put it like this:
<Image source={require(uriAbove)} />
react-native crashes with error:
Unknown named module: 'file:///data/user/0/com.coach/cache/ReactNative-snapshot-image1317300113.png'

Any idea what I can do about it?

(Android) Trying to resolve view with tag which doesn't exist

I'm getting this issue if my view reference did not specify a backgroundColor.

so the code works fine if I take a Snapshot with the below viewRef

<View   
  style={{backgroundColor: 'yellow'}}   
  ref={ref => viewRefSuccess = ref}>   
  <Text>   
    Hello View Snap Shot   
  </Text>   
</View>   

However it will crash with the "Trying to resolve view with tag 'tagID' which doesn't exist"
if I remove the backgroundColor props.

<View ref={ref => viewRefSuccess = ref}>   
  <Text>   
    Hello View Snap Shot   
  </Text>   
</View>   

Any thought on why this is happening?

Thanks.

Image Resolution Doubled?

When I load an image into a view and then use react-native-view-shot to create an image from that view the resolution seems to be doubled.

I don't think I'm doing anything weird...

Here is the function I'm using to take the image:

        console.log('taking picture of size: ', width, height);
        RNViewShot.takeSnapshot(this.refs['layout'], {
            format: 'png',
            quality: 0.8,
            width,
            height
        })
        .then(
            uri => {
                console.log('Image saved to', uri);
                Image.getSize(uri, (width, height) => {
                    console.log(`Image dimensions: ${width}x${height}`);
                });
            },
            error => console.error('Oops, snapshot failed', error)
        );
    }

And the output:

[PERF ASSETS] Loading image at size {3600, 3600}, which is larger than the screen size {750, 1334}
index.ios.js:21 taking picture of size:  3600 3600
index.ios.js:30 Image saved to /Users/chris/Library/Developer/CoreSimulator/Devices/A0EC9E9C-B184-46B8-80BE-DCCA88E4C699/data/Containers/Data/Application/2552626F-31AC-4F3D-86BF-12EFCC163100/tmp/ReactNative/DB9581E0-E465-460C-A3E9-FC904218C47E.png
index.ios.js:32 Image dimensions: 7200x7200

Take snapshot, when Component is ready

Part of my snapshot is an Image, which is fading in, when the image is loaded and displayed the first time. When I take a snapshot, while the image is still not completely displayed, I get a grayed out image.

Is there a way to trigger the snapshot, when the View is ready and rendered completely?

What I am currently doing is trigger the snapshot with onLayout of the outer View and a relatively long timer, that waits another second, before the snapshot is taken. But that is making my app less responsive and sometimes the image is still not there, when the snapshot fires. I tried onLoad and onLayout of the Image, but those did not work any better.

Any Idea?

Thanks, Tim

WebView charts captures blank

webview source require this html,captures blank, in the react-native-view-shot-example project @gre

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>ECharts</title>
  <!-- 引入 echarts.js -->
  <script src="http://cdn.bootcss.com/echarts/3.4.0/echarts.min.js"></script>
</head>

<body>
  <!-- 为ECharts准备一个具备大小(宽高)的Dom -->
  <div id="main" style="width: 600px;height:400px;"></div>
  <script type="text/javascript">
    // 基于准备好的dom,初始化echarts实例
    var myChart = echarts.init(document.getElementById('main'));

    // 指定图表的配置项和数据
    var symbolSize = 20;
    var data = [[15, 0], [-50, 10], [-56.5, 20], [-46.5, 30], [-22.1, 40]];
    var points = [];

    option = {
      title: {
        text: 'Click to Add Points'
      },
      tooltip: {
        formatter: function (params) {
          var data = params.data || [0, 0];
          return data[0].toFixed(2) + ', ' + data[1].toFixed(2);
        }
      },
      grid: {
        left: '3%',
        right: '4%',
        bottom: '3%',
        containLabel: true
      },
      xAxis: {
        min: -60,
        max: 20,
        type: 'value',
        axisLine: { onZero: false }
      },
      yAxis: {
        min: 0,
        max: 40,
        type: 'value',
        axisLine: { onZero: false }
      },
      series: [
        {
          id: 'a',
          type: 'line',
          smooth: true,
          symbolSize: symbolSize,
          data: data
        }
      ]
    };

    // 使用刚指定的配置项和数据显示图表。
    myChart.setOption(option);
  </script>
</body>

</html>

Requiring unknown module "/data/data/..." on Android

I can't seem to Image.getSize nor require() the saved image on Android. Works fine on iOS.

takeSnapshot(this.refs.content, {
    format: 'jpeg',
    quality: 0.8,
})
.then((response) => {
    Image.getSize(response, (width, height) => {
        this.setState({
            modalBackdropProps: {
                imageSize: {
                    height,
                    width,
                },
                source: {
                    uri: response,
                },
            },
        });
    });
});

The image path is: /data/data/<packageName>/cache/ReactNative_snapshot_image_<timestamp>.jpeg.

For Image.getSize I get: "Error: Unsupported uri scheme!"

Refview question

Can anyone give me an example of how to implement the Refview?
I just put view there, and it throws an error 'ExceptionsManager.js:71 Unhandled JS Exception: findNodeHandle(...): Argument is not a component (type: function, keys: displayName,AccessibilityTraits,AccessibilityComponentType,forceTouchAvailable,propTypes)'

Many thanks,
Ian

Cannot read property 'takeSnapshot' of undefined

Hey so I'm having this issue. I can't seem to figure out if this is something that I'm doing wrong or an actual issue with the package. Please help!
simulator screen shot sep 29 2016 6 00 06 pm

The code:

snapshot = view => () => takeSnapshot(this.refs[view], { format: "jpeg", quality: 0.8 }) .then( uri => console.log("Image saved to", uri), error => console.error("Oops, snapshot failed", error) )

and

<View ref = "main"> <Button rounded danger style = {{ width: 55, height: 55 }} onPress = {this.snapshot("main")} > test </Button> </View>

Introduce a `<Snapshotable>` to make it easier ?

just the reason we (most of the time!) needs to do collapsable={false} on Android, and sometimes even needs to wrap a parent <View collapsable={false}> (e.g. WebView) makes me think maybe we should hide that from the lib user ( note https://github.com/gre/react-native-view-shot#specific-to-android-implementation ).

Maybe the library should (only?) be available through a wrapper Component.

<Snapshotable ref="snap"> ... </Snapshotable>

snap.capture().then(...

WDYT?

one downside is introducing a <View> wrapping changes the hierarchy.

available for surfaceview screenshot ?

My app use surfaceview to display the video,and I want to take a screenshot to share to other people when i play the video, i have tried many ways,but did'n work,what i got is black screen, so I want to ask this program can be used to take a screenshot of surfaceview ? Any advice will be appreciated.

Getting errors with 1.6.0 after upgrading to RN 0.40 🙏 😢

So I upgraded to RN 0.40 and everything broke. So now I'm trying to go through each library I used and hopefully get it working again.

I upgraded to 1.6.0 and can't get the project to build, with errors like:
image

/MY_APP_LOCATION/node_modules/react-native-view-shot/ios/RNViewShot.m:31:16: Property 'uiManager' cannot be found in forward class object 'RCTBridge'

I npm install the 1.6.0 and react-native unlink react-native-view-shoted then react-native link react-native-view-shoted and cleaned project in xCode but still not compiling. One of the errors is coming from this library as shown in the image above.

Any ideas on how to fix this please 🙏?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.