UI thread rendering
Description
Hey,
Apologies if this is already out there. Is there any plan to offer rendering off the main thread similar to Reanimated?
It would be handy for animations to continue when the JS thread is blocked (doing compute), especially for gestures.
Here is an example (code below). Panning on the x-axis uses Reanimated, and panning on the y-axis uses Skia. A blocking function runs every 3 seconds.
import * as skia from "@shopify/react-native-skia";
import { useEffect } from "react";
import { useWindowDimensions, View } from "react-native";
import { Gesture, GestureDetector, GestureHandlerRootView } from "react-native-gesture-handler";
import Animated, { useAnimatedStyle, useSharedValue } from "react-native-reanimated";
const block = () => {
for (let i = 0; i < 50000000; i++) {}
};
export const Root = (): JSX.Element => {
const { width, height } = useWindowDimensions();
useEffect(() => {
const i = setInterval(block, 3000);
return () => clearInterval(i);
}, []);
const xPositionReanimated = useSharedValue(0);
const yPositionReanimated = useSharedValue(0);
const panGesture = Gesture.Pan().onChange((e) => {
xPositionReanimated.value += e.changeX;
yPositionReanimated.value += e.changeY;
});
const reanimatedStyle = useAnimatedStyle(() => ({
translateX: xPositionReanimated.value,
}));
const skiaY = skia.useValue(0);
skia.useSharedValueEffect(() => {
skiaY.current = yPositionReanimated.value;
}, yPositionReanimated);
return (
<View style={{ width, height }}>
<GestureHandlerRootView>
<GestureDetector gesture={panGesture}>
<Animated.View style={reanimatedStyle}>
<skia.Canvas style={{ height: height, width: width }}>
<skia.Rect x={0} y={skiaY} height={100} width={100} color="red" />
</skia.Canvas>
</Animated.View>
</GestureDetector>
</GestureHandlerRootView>
</View>
);
};
Simpler example only using Skia
const block = () => {
for (let i = 0; i < 50000000; i++) {
}
}
export default function App() {
const { width, height } = useWindowDimensions();
const animatedX = skia.useTiming({ loop: true, yoyo: true, from: 0, to: width - 100 })
return (
<View style={{ width, height }}>
<skia.Canvas style={{ width: width, height: 300 }}>
<skia.Rect x={animatedX} y={100} width={100} height={100} color="blue"/>
</skia.Canvas>
<Button title="Click to block the JS thread" onPress={() => block()}/>
</View>
);
}
Hi @louix! Thanks for suggesting this :) It is not available yet - but this is definitely a feature we're looking forward to release :) We showed some examples of it in the latest video on @wcandillon 's channel and we're working hard to bring this to you all 🥳
We are now rendering the UI thread but most animations need to be done via the JS thread at the moment, we are looking at the next steps there.
As @wcandillon says, from version Release 0.1.159 beta we're rendering on the main thread - which should offer rendering on first frame - so I'm closing this issue :)
PS. Eventually we'll also start updating our computed animation values using workouts as well.