Shopify / react-native-skia

High-performance React Native Graphics using Skia
https://shopify.github.io/react-native-skia
MIT License
6.8k stars 437 forks source link

SVG's from react-native-svg don't appear in skia snapshots (makeImageFromView) only Android #2555

Open dani-benet opened 1 month ago

dani-benet commented 1 month ago

Description

I'm creating a popper-like component that snapshots a component and puts the image in top of a dark overlay ->

https://github.com/user-attachments/assets/2ffd3699-2b08-4d1a-9711-ddb1cde2c4a2

But I'm facing an issue on Android where the SVG's created using react native reanimated are not shown in the snapshots. See on the next video the cursor on the top-left disappears.

https://github.com/user-attachments/assets/e85e7e68-b5db-4003-879d-b862606cedcd

Version

1.3.9 and also tried it on 1.2.3

Steps to reproduce

Make a snapshot of any svg in Android and it doesn't work.

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

I've managed to reproduce the issue with this sample code

import {
  Canvas,
  Image,
  makeImageFromView,
  SkImage,
} from "@shopify/react-native-skia"
import { useRef, useState } from "react"
import { Button, View } from "react-native"
import Close from "~assets/icons/close.svg"

const Home = () => {
  const ref = useRef<View>(null)
  const [snapshot, setSnapshot] = useState<SkImage | null>(null)

  const handleImageCreation = async () => {
    const _snapshot = await makeImageFromView(ref)
    setSnapshot(_snapshot)
  }

  return (
    <View style={{ alignItems: "center", justifyContent: "center", flex: 1 }}>
      <View ref={ref} collapsable={false}>
        <Close style={{ height: 40, width: 40 }} />
      </View>
      {snapshot && (
        <Canvas style={{ height: 40, width: 40 }}>
          <Image image={snapshot} x={0} y={0} width={40} height={40} />
        </Canvas>
      )}
      <Button onPress={handleImageCreation} title="Create Image" />
    </View>
  )
}

on iOS it's visible but not on Android

iOS Android
image android card not working

To render the svg I use the react-native-svg library

  declare module "*.svg" {
    import React from "react"
    import { SvgProps } from "react-native-svg"
    const content: React.FC<SvgProps>
    export default content
  }
wcandillon commented 1 month ago

@WoLewicki it looks like RN SVG is using a type of view that we are not handling there: https://github.com/Shopify/react-native-skia/blob/main/package/android/src/main/java/com/shopify/reactnative/skia/ViewScreenshotService.java#L123

We handle SurfaceView and TextureView, but maybe RN SVG is using something else?

WoLewicki commented 1 month ago

Hmm, react-native-svg views extend ReactViewGroup: https://github.com/software-mansion/react-native-svg/blob/acd29d74682f04a53336b716dec0e98af8d0fa01/android/src/main/java/com/horcrux/svg/SvgView.java#L37, https://github.com/software-mansion/react-native-svg/blob/acd29d74682f04a53336b716dec0e98af8d0fa01/android/src/main/java/com/horcrux/svg/VirtualView.java#L32.

We override onDraw: https://github.com/software-mansion/react-native-svg/blob/acd29d74682f04a53336b716dec0e98af8d0fa01/android/src/main/java/com/horcrux/svg/SvgView.java#L125 so this might be not handled properly by react-native-skia? Not sure though.

wcandillon commented 1 month ago

Thanks this is very helpful. If gre/react-native-view-shot handles it well, we will be able to do it as well: https://github.com/gre/react-native-view-shot/blob/master/android/src/main/java/fr/greweb/reactnativeviewshot/ViewShot.java

WoLewicki commented 1 month ago

I'd guess react-native-svg views propably go here: https://github.com/Shopify/react-native-skia/blob/aadd424a5a9be215fee5f400ae0029a0180ad367/package/android/src/main/java/com/shopify/reactnative/skia/ViewScreenshotService.java#L86 and then here: https://github.com/Shopify/react-native-skia/blob/aadd424a5a9be215fee5f400ae0029a0180ad367/package/android/src/main/java/com/shopify/reactnative/skia/ViewScreenshotService.java#L110-L114 and I think it is not the proper way.