Skip to content

Instantly share code, notes, and snippets.

@terrysahaidak
Last active October 26, 2023 17:13
Show Gist options
  • Save terrysahaidak/4d2aaf0373a890b3ce8e85a2f84bb5eb to your computer and use it in GitHub Desktop.
Save terrysahaidak/4d2aaf0373a890b3ce8e85a2f84bb5eb to your computer and use it in GitHub Desktop.
Slow SKIA scroll gesture
import {Canvas, RoundedRect} from '@shopify/react-native-skia';
import React from 'react';
import {StyleSheet, View} from 'react-native';
import {
Gesture,
GestureDetector,
GestureHandlerRootView,
ScrollView,
} from 'react-native-gesture-handler';
import {PanGesture} from 'react-native-gesture-handler/lib/typescript/handlers/gestures/panGesture';
import Animated, {
useAnimatedScrollHandler,
useDerivedValue,
useSharedValue,
withDecay,
} from 'react-native-reanimated';
function Rect({index, offset}) {
const y = useDerivedValue(() => {
return offset.value + 150 * index + 50;
});
return (
<RoundedRect x={30} y={y} width={200} height={100} r={16} color="red" />
);
}
const array = new Array(30).fill(0).map((_, index) => index);
function App() {
const offset = useSharedValue(0);
const onScroll = useAnimatedScrollHandler({
onScroll: event => {
requestAnimationFrame(() => {
offset.value = event.contentOffset.y * -1;
});
},
});
const panGesture = Gesture.Pan()
.onBegin(event => {})
.onChange(event => {
requestAnimationFrame(() => {
offset.value += event.changeY;
});
})
.onEnd(event => {
offset.value = withDecay({
velocity: event.velocityY,
deceleration: 0.998,
});
});
return (
<GestureHandlerRootView style={{flex: 1}}>
<View style={{flex: 1}}>
<Canvas mode="continuous" style={StyleSheet.absoluteFill}>
{array.map(index => (
<Rect key={index} index={index} offset={offset} />
))}
</Canvas>
{/* <GestureDetector gesture={panGesture}> */}
<Animated.View style={StyleSheet.absoluteFill}>
<Animated.ScrollView onScroll={onScroll} scrollEventThrottle={1}>
<View style={{height: 10000}} />
</Animated.ScrollView>
</Animated.View>
{/* </GestureDetector> */}
</View>
</GestureHandlerRootView>
);
}
export default App;
import { Canvas, RoundedRect, useValue, useSharedValueEffect, useComputedValue } from '@shopify/react-native-skia';
import React from 'react';
import { StyleSheet, View } from 'react-native';
import Animated, { useAnimatedScrollHandler, useSharedValue } from 'react-native-reanimated';
function Rect({ index, offset }) {
const y = useComputedValue(() => {
return offset.current + 150 * index + 50;
}, [offset]);
return <RoundedRect x={30} y={y} width={200} height={100} r={16} color="red" />;
}
const array = new Array(30).fill(0).map((_, index) => index);
function App() {
const offset = useSharedValue(0);
const offsetSkia = useValue(0);
useSharedValueEffect(() => {
offsetSkia.current = offset.value;
}, offset);
const onScroll = useAnimatedScrollHandler({
onScroll: (event) => {
offset.value = event.contentOffset.y * -1;
},
});
return (
<View style={{ flex: 1 }}>
<Canvas mode="continuous" style={StyleSheet.absoluteFill}>
{array.map((index) => (
<Rect key={index} index={index} offset={offsetSkia} />
))}
</Canvas>
<Animated.View style={StyleSheet.absoluteFill}>
<Animated.ScrollView onScroll={onScroll} scrollEventThrottle={1}>
<View style={{ height: 10000 }} />
</Animated.ScrollView>
</Animated.View>
</View>
);
}
export default App;
import {Canvas, Group, RoundedRect} from '@shopify/react-native-skia';
import React from 'react';
import {StyleSheet, View} from 'react-native';
import {
Gesture,
GestureDetector,
GestureHandlerRootView,
ScrollView,
} from 'react-native-gesture-handler';
import {PanGesture} from 'react-native-gesture-handler/lib/typescript/handlers/gestures/panGesture';
import Animated, {
useAnimatedScrollHandler,
useDerivedValue,
useSharedValue,
withDecay,
} from 'react-native-reanimated';
function Rect({index, offset}) {
// const y = useDerivedValue(() => {
// return offset.value + 150 * index + 50;
// });
return (
<RoundedRect
x={30}
y={150 * index + 50}
width={150}
height={100}
r={16}
color="red"
/>
);
}
function RectRN({index, offset}) {
// const y = useDerivedValue(() => {
// return offset.value + 150 * index + 50;
// });
return (
<View
left={30}
top={50 + 50 * index}
width={150}
height={100}
borderRadius={16}
backgroundColor="green"
/>
);
}
const array = new Array(30).fill(0).map((_, index) => index);
function App() {
const offset = useSharedValue(0);
const onScroll = useAnimatedScrollHandler({
onScroll: event => {
requestAnimationFrame(() => {
offset.value = event.contentOffset.y * -1;
});
},
});
const panGesture = Gesture.Pan()
.onBegin(event => {})
.onChange(event => {
requestAnimationFrame(() => {
offset.value += event.changeY;
});
})
.onEnd(event => {
offset.value = withDecay({
velocity: event.velocityY,
deceleration: 0.998,
});
});
return (
<GestureHandlerRootView style={{flex: 1}}>
<View style={{flex: 1}}>
<View style={{flexDirection: 'row', flex: 1}}>
<Canvas mode="continuous" style={[{flex: 1}]}>
<Group
transform={useDerivedValue(() => {
return [{translateY: offset.value}];
})}>
{array.map(index => (
<Rect key={index} index={index} offset={offset} />
))}
</Group>
</Canvas>
<View
mode="continuous"
style={{
flex: 1,
}}>
<Animated.View
style={{
transform: [
{
translateY: useDerivedValue(() => {
return offset.value;
}),
},
],
}}>
{array.map(index => (
<RectRN key={index} index={index} offset={offset} />
))}
</Animated.View>
</View>
</View>
{/* <GestureDetector gesture={panGesture}> */}
<Animated.View style={StyleSheet.absoluteFill}>
<Animated.ScrollView onScroll={onScroll} scrollEventThrottle={1}>
<View style={{height: 10000}} />
</Animated.ScrollView>
</Animated.View>
{/* </GestureDetector> */}
</View>
</GestureHandlerRootView>
);
}
export default App;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment