Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This PR adds implementation of `measure` and `scrollTo` functions on web. The following example verifies the implementation using a component with non-zero `margin`, `padding`, and `borderWidth`. The results are identical to those from `measure` from React Native. `measure` doesn't work when Chrome Debugger is attached because in such case worklets are executed on the main JS context (like on web, but it's still React Native, so we can't just check HTMLElement size). <details> <summary>MeasureExample.tsx</summary> ```tsx import Animated, { measure, runOnUI, useAnimatedRef, useAnimatedStyle, useSharedValue, withTiming, } from 'react-native-reanimated'; import { Button, ScrollView, View } from 'react-native'; import React from 'react'; export default function MeasureExample() { const aref = useAnimatedRef<Animated.View>(); const ref = React.useRef(0); const sv = useSharedValue(0); const handleAnimateWidth = () => { ref.current = 1 - ref.current; sv.value = withTiming(ref.current, { duration: 1500 }); }; const handleMeasureFromJS = () => { aref.current?.measure((x, y, width, height, pageX, pageY) => console.log({ width, height, x, y, pageX, pageY }) ); }; const handleMeasureFromUI = () => { runOnUI(() => { 'worklet'; console.log(measure(aref)); })(); }; const animatedStyle = useAnimatedStyle(() => { return { width: 80 + 100 * sv.value, height: 80, margin: 10, padding: 10, borderWidth: 10, borderColor: 'blue', backgroundColor: 'navy', }; }, []); return ( <View style={{ flexDirection: 'column', marginHorizontal: 'auto' }}> <View> <Button onPress={handleAnimateWidth} title="Animate width" /> <Button onPress={handleMeasureFromJS} title="Measure from JS" /> <Button onPress={handleMeasureFromUI} title="Measure from UI" /> </View> <View> <ScrollView style={{ height: 400 }}> <View style={{ paddingVertical: 350, backgroundColor: 'lightgray' }}> <ScrollView style={{ width: 400 }} horizontal> <View style={{ paddingHorizontal: 350, backgroundColor: 'lightgray', }}> <Animated.View ref={aref} style={animatedStyle} /> </View> </ScrollView> </View> </ScrollView> </View> </View> ); } ``` </details> <details> <summary>ScrollToExample.tsx</summary> ```tsx import Animated, { runOnUI, scrollTo, useAnimatedRef, } from 'react-native-reanimated'; import { Button, Switch, Text, View } from 'react-native'; import React from 'react'; export default function ScrollToExample() { const [animated, setAnimated] = React.useState(true); const aref = useAnimatedRef<Animated.ScrollView>(); const scrollFromJS = () => { aref.current?.scrollTo({ y: Math.random() * 2000, animated }); }; const scrollFromUI = () => { runOnUI(() => { 'worklet'; scrollTo(aref, 0, Math.random() * 2000, animated); })(); }; return ( <View> <Switch value={animated} onValueChange={setAnimated} /> <Button onPress={scrollFromJS} title="Scroll from JS" /> <Button onPress={scrollFromUI} title="Scroll from UI" /> <Animated.ScrollView ref={aref} style={{ width: 200, height: 400 }}> {[...Array(100)].map((_, i) => ( <Text key={i} style={{ fontSize: 50, textAlign: 'center' }}> {i} </Text> ))} </Animated.ScrollView> </View> ); } ``` </details> https://user-images.githubusercontent.com/20516055/194900280-45ad84bc-77ac-4ee3-af15-931d56d1516b.mov https://user-images.githubusercontent.com/20516055/194924529-96644d3c-0388-489d-bb65-3e80564acd41.mov Tested with: - [x] Example app: - [x] Example app with Chrome Debugger (I had to disable Hermes in Podfile and use JSC instead because otherwise React DevTools didn't work) - [x] WebExample (Firefox, Chrome, Safari)
- Loading branch information