react-native-skia icon indicating copy to clipboard operation
react-native-skia copied to clipboard

Canvas resizes in an animated manner by default

Open laurens-lamberts opened this issue 3 years ago • 1 comments

Hello :)

I noticed that by default, a react-native-skia canvas resizes in an animated way. This is demonstrated in the video below, using an example I made.

When I do set the canvas size to fixed values, the animated scaling does not happen. This is shown in the second video.

I think that it would be more logical if a canvas resize is drawn instantly, instead of animated resizing. It is a nice option to have, though. Maybe this could be a configuration option on the canvas?

Specifically I noticed this 'issue' in our production app. For this app we use an image header. The Skia canvas in this image header has its width set to the width of the screen, coming from the react-native Dimensions API. It seems to me that sometimes a Skia canvas is already rendered before the definitive screen width is coming through, because sometimes (rarely though) I do see this animated resize happen (scaling out from the left upper corner) in our production app.

Curious what you think about this. Have a nice day!

https://user-images.githubusercontent.com/48212886/181081398-f7b16bcd-b0cb-4875-973e-b3ed785df829.mov

https://user-images.githubusercontent.com/48212886/181082323-566377c0-b68b-4b46-8af2-49a5c6d86316.mov

laurens-lamberts avatar Jul 26 '22 18:07 laurens-lamberts

Hi @laurens-lamberts! This is definitely not intended from our side - so this is just magic happening somewhere 🦄

I think we should look into this and find out where this animation is coming from, I have seen similar behaviour when developing, but never thought about it this way.

Thanks for reporting it :)

chrfalch avatar Jul 27 '22 08:07 chrfalch

A solution for this was found when converting the DOM renderer to C++ so this should now be fixed!

chrfalch avatar Nov 20 '22 10:11 chrfalch

#1027 Native Skia Dom

chrfalch avatar Nov 20 '22 10:11 chrfalch

Hi @chrfalch,

Great to hear that a solution to this has been found! Do you know if this is already included in the latest release (0.1.165)? When I test that version, I still experience these animated resizing/drawing, but from the left side now, instead of the left upper corner.

Thanks a lot for all of your work on this. Laurens

laurens-lamberts avatar Dec 14 '22 09:12 laurens-lamberts

Hi @laurens-lamberts - yeah, we thought we'd fixed them, but my test was obviously testing the wrong thing. I see the same as you.

chrfalch avatar Dec 14 '22 09:12 chrfalch

Hey! I believe I'm experiencing the same thing when drawing SVGs within a canvas. Just wondering what the status is with this issue? :)

https://user-images.githubusercontent.com/5165963/213175925-9c0ad43b-e631-4164-80c2-65ab8550c533.mp4

Braden1996 avatar Jan 18 '23 12:01 Braden1996

Thanks for reporting this - We will look into this. It is only on iOS, right? I think I know where / what this is...

chrfalch avatar Jan 18 '23 12:01 chrfalch

Thanks for reporting this - We will look into this. It is only on iOS, right? I think I know where / what this is...

Yep - this seems to just happen for iOS. For my particular use case, I've deferred mounting the Canvas until the surrounding onLayout measurements have happened; after which the image fades in. Reduces some of the janky feel.

Braden1996 avatar Jan 18 '23 14:01 Braden1996

I tool the example @laurens-lamberts wrote and adapted it so it is easy to replace the contents of our App.tsx file (in the example project) to reproduce the issue:

import React, { useEffect, useState } from "react";
import { Canvas, Image, useImage } from "@shopify/react-native-skia";
import { View } from "react-native";

const START_SIZE = 200;

const App = () => {
  const [imageSize, setImageSize] = useState(START_SIZE);

  useEffect(() => {
    let interval = setInterval(() => {
      setImageSize(Math.random() * 200 + START_SIZE);
    }, 1000);
    return () => {
      if (interval) clearInterval(interval);
    };
  }, []);

  const skiaImage = useImage(require("./assets/oslo.jpg"));

  return (
    <View style={{ margin: 12 }}>
      <Canvas
        style={{
          width: imageSize,
          height: imageSize,
        }}
      >
        {!!skiaImage && (
          <Image
            x={0}
            y={0}
            width={imageSize}
            height={imageSize}
            image={skiaImage}
            fit="cover"
          />
        )}
      </Canvas>
    </View>
  );
};

// eslint-disable-next-line import/no-default-export
export default App;

chrfalch avatar Jan 19 '23 07:01 chrfalch

@laurens-lamberts and @Braden1996 - Please look at the PR I've made and see if it fixes the issues you're having. It is a super simple fix that can be tested directly in the node_modules/@shopify/react-native-skia folder.

chrfalch avatar Jan 19 '23 10:01 chrfalch

Hi @chrfalch, thanks a lot for the fix! Just tested it on my example app, and that works perfectly fine. CC @Braden1996

laurens-lamberts avatar Jan 19 '23 20:01 laurens-lamberts