react-native-skia: Buggy .makeImageSnapshot() on IOS

Description

When I want to snapshot my Skia canvas (which is not that small), it gets buggy. These bugs don’t occur always. If you try it multiple times, you will see that sometimes it works fine.

Screenrecording of the bug: https://www.youtube.com/shorts/mH7VuiT7CuU

What bugs?:

  • For a short period of time, the elements of my canvas get transformed in a weird way
  • Outputted image doesn’t contain all items of canvas sometimes

Does RNSkia somehow rerender the Canvas, when the method makeImageSnapshot gets executed? If yes, I think, the snapshot is taken before the rerender process is completely finished.

It makes no sense to me, since the only code that gets triggered on the button click is this one:

const handleShare = async () => {
    const image = canvasRef.current?.makeImageSnapshot();

    if (image) {
      const base64Image = image.encodeToBase64();
      const options = {
        mimeType: 'image/jpeg',
        dialogTitle: 'Share the image',
        UTI: 'public.jpeg',
      };
      const fileUri = FileSystem.documentDirectory + 'test.jpeg'; // todo ts name name
      await FileSystem.writeAsStringAsync(fileUri, base64Image, {
        encoding: FileSystem.EncodingType.Base64,
      });

      Sharing.shareAsync(fileUri, options)
        .then((data: any) => {
          console.log('SHARED');
        })
        .catch((err: any) => {
          console.log(JSON.stringify(err));
        });
    }
  };

Version

0.1.197 in repro but also appears in 0.1.202

Steps to reproduce

How to reproduce:

npm install

On Mac simulator npx expo run:ios

On Iphone with EAS eas build --profile development --platform ios npx expo start --dev-client

In the App

<div> 1) Select background image from gallery </div> <div> 2) Select overlaying design image from gallery </div> <div> </div>

Snack, code example, screenshot, or link to a repository

I couldn’t really reproduce this in any test projects sadly. This only happened in my big project, i guess its because it has more heavy operations.

https://github.com/sravis02/flashes-app Branch: issue-react-native-skia I invited you both (chrfalch & wcandillion) to my repository

The Canvas is in PreviewCanvas.tsx The Snapshotfunction in preview.tsx

About this issue

  • Original URL
  • State: closed
  • Created 10 months ago
  • Reactions: 1
  • Comments: 19

Most upvoted comments

thanks a lot, this workaround works for me 😃 @ludwighen

Following up on this, I think I found a workaround for the issue @cesargdm.

Indeed I have the same issue and I first thought it would only happen in my development builds but it also happened in production, only for less powerful devices. It was probably visible in the development builds because they are a bit less performant, and something obviously tries to render the moment the snapshot is taken. I assume in most attempts it’s fast enough to take the image after this drawing process.

I figured what if I just delay the makeImageScreenshot by one render cycle using setTimeout. And it works. I have no idea why 😅, but with over 100 attempts, I now can no longer reproduce the issue, so I believe it fixed it. Let me know if it works for you too.

Here’s my code:

  const onSavePress = useCallback(async () => {
   //... some other stuff

    setTimeout(() => {
      const image = ref.current?.makeImageSnapshot();
      if (!image) {
        // handle error
        return;
      }

      setSkiaImage(image);
    }, 0);
  }, [ref]);