Last active
January 31, 2024 03:31
-
-
Save syaau/ea8dcf1541276aef70aae0d68ef6f8b7 to your computer and use it in GitHub Desktop.
Demo Canvas App to re-render multple times which uses the UI thread completely in few seconds.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useEffect, useState } from 'react'; | |
import { Canvas, RoundedRect } from '@shopify/react-native-skia'; | |
import { useSharedValue, withRepeat, withSequence, withTiming } from "react-native-reanimated"; | |
import { Dimensions } from 'react-native'; | |
// Number of cards to render | |
const items = 50; | |
// Array of cards with unique id | |
const cards = new Array(items).fill(null).map((_, idx) => `k-${idx}`) | |
export function CanvasApp() { | |
const [allCards, setCards] = useState(cards); | |
useEffect(() => { | |
// Sort the cards randomly in high frequency to change the | |
// order, and trigger render | |
setInterval(() => { | |
const newCards = cards.slice(0); | |
newCards.sort(() => Math.random() - 0.5); | |
setCards(newCards); | |
}, 100); | |
}, []); | |
return ( | |
<Canvas style={{flex: 1}} renderToHardwareTextureAndroid shouldRasterizeIOS> | |
{allCards.map((k, idx) => <Card key={k} />)} | |
{/* {allCards.map((k) => <RoundedRect key={k} x={0} y={0} width={70} height={120} color='red' r={4} />)} */} | |
</Canvas> | |
) | |
} | |
let { width, height } = Dimensions.get('screen'); | |
width = width - 70; | |
height = height - 120; | |
/** | |
* A card component rendered a simple RoundedRect canvas shape. An animation has | |
* been played just to make the things look playful. | |
* @returns | |
*/ | |
export function Card() { | |
const [color] = useState(Math.floor((Math.random() * 0xffffff)) + 0xff000000); | |
const x = useSharedValue(Math.random() * width) | |
const y = useSharedValue(Math.random() * height); | |
useEffect(() => { | |
const speed = 0.1 + (Math.random()) / 10; | |
const widthDuration = width / speed; | |
const heightDuration = height / speed; | |
const toX = x.value > width / 2 ? 1 : 0; | |
const toY = y.value > height / 2 ? 1 : 0; | |
const xDuration = Math.abs(toX - x.value) / speed; | |
const yDuration = Math.abs(toY - y.value) / speed; | |
x.value = withSequence(withTiming(toX * width, { duration: xDuration }), withRepeat( | |
withSequence( | |
withTiming((1 - toX) * width, { duration: widthDuration }), | |
withTiming(toX * width, { duration: widthDuration }) | |
), -1 | |
)); | |
y.value = withSequence(withTiming(toY * height, { duration: yDuration }), withRepeat( | |
withSequence( | |
withTiming((1 - toY) * height , { duration: heightDuration }), | |
withTiming(toY * height, { duration: heightDuration }) | |
), -1 | |
)); | |
}, []) | |
return ( | |
<RoundedRect x={x} y={y} width={70} height={120} color={color} r={4}/> | |
) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment