react-native-skia
react-native-skia copied to clipboard
[Android] Canvas resizing is janky on Android
Hello, thanks again for making such a fantastic library!
I'm here to report an issue with resizing Canvas
with onLayout
(or any other methods) on Android. I have console logged the LayoutChangeEvent
and ensured that the component is only re-rendered once when the layout changes.
Android Demo
https://user-images.githubusercontent.com/6837599/167069421-7630350b-3350-4eae-9b3e-3d7d07bb3a3a.mp4
iOS Demo
https://user-images.githubusercontent.com/6837599/167069443-bbe1e2e3-5948-4212-a107-83d6365f855e.mov
Minimal Repro
import React, { useState } from 'react';
import { Button, Dimensions, View } from 'react-native';
import { Canvas, Group, RoundedRect, Shadow } from '@shopify/react-native-skia';
const { width } = Dimensions.get('window');
const PADDING = 32;
const WIDTH = width - PADDING;
const HomeContent = () => {
const [change, setChange] = useState(false);
const [height, setHeight] = useState(0);
return (
<View>
<View style={{ height: height + PADDING }}>
<Canvas style={{ flex: 1 }}>
<Group>
<Shadow dx={0} dy={10} blur={5} color="rgba(179, 197, 234, 0.6)" />
<Shadow
dx={2}
dy={2}
blur={4}
color="rgba(238, 243, 255, 0.75)"
inner
/>
<Shadow
dx={-4}
dy={-4}
blur={8}
color="rgba(223, 230, 245, 1)"
inner
/>
<RoundedRect
x={PADDING / 2}
y={0}
width={WIDTH}
height={height}
r={20}
color="white"
/>
</Group>
</Canvas>
{change ? (
<View
style={{ position: 'absolute', height: 100 }}
onLayout={event => {
setHeight(event.nativeEvent.layout.height);
}}
/>
) : (
<View
style={{ position: 'absolute', height: 200 }}
onLayout={event => {
setHeight(event.nativeEvent.layout.height);
}}
/>
)}
</View>
<Button
title="Change Layout"
onPress={() => {
setChange(!change);
}}
/>
</View>
);
};
export default HomeContent;
Can you use box-shadow instead: https://shopify.github.io/react-native-skia/docs/shapes/box? These inner shadows a notoriously slow especially on Android. They should only be used for complex shapes like paths or text.
@wcandillon Hey William, thank you for the suggestion! I saw your Neumorphism video but forgot to use it here 😅. However, I tried it out and while it is slightly faster, I am still getting the same weird resizing effect on Android. Furthermore, there's an additional random graphical glitch now, and it is appearing outside of the Canvas
that I am resizing as well:
Hi @wcandillon, after updating the small top right button to use BoxShadow
as well, the problem has been magnified on Android. It still works great on iOS though. Will there be any investigation done into this issue? Thank you very much!
https://user-images.githubusercontent.com/6837599/168550464-d6c92da9-1197-4aae-9107-2c61c42c46dd.mp4
Should use the size as a Skia value (https://shopify.github.io/react-native-skia/docs/animations/values#canvas). I played with it a little bit and it seems to work nicely. And also to offer the performance level you need?
@wcandillon Just tried this and it does sort of improve the situation on Android, as I no longer see inconsistent Canvas sizes and graphical glitches. However, it is still stuttery and less than ideal, but we can live with it for now.
However, we would like to report that using BoxShadow
is still causing intense graphical glitches as seen above. Switching back to the regular Shadow
is actually performing much better on Android for us.
I would like to investigate this further. Is the code snippet under "Minimal Repro" still the source of truth there, or you have an updated minimal example I should be looking at? Let's get to the bottom of this.
@wcandillon sorry for the late reply, yes the Minimal Repro is still valid here to reproduce jank, but if you would like to reproduce the intense graphical glitches that I experienced on Android as well, you just need to convert it to use BoxShadow
. It might also make the issue more obvious if you have multiple Canvas
rendering BoxShadow
, as I am doing in my application. Thank you!
@wcandillon on production, the jank is almost gone with Shadow
. The only 'issue' left here is the visual glitch caused by animating BoxShadow
maybe? But thank you for the fix shown above!