React-native-реанимированный 2: Как обновить текст в ответ на PanGestureHandler?

#react-native #react-native-reanimated #react-native-gesture-handler #react-native-reanimated-v2

Вопрос:

Вот мой компонент. Это просто PanGestureHandler с некоторыми svg.

 import React from 'react'
import { StyleSheet, View, Text } from 'react-native'
import Svg, { Circle, Line } from 'react-native-svg'
import Layout from '../constants/Layout'
import {
  PanGestureHandler,
  TapGestureHandler
} from 'react-native-gesture-handler'
import Animated, {
  useSharedValue,
  useAnimatedGestureHandler,
  useAnimatedProps,
  withTiming,
  Easing
} from 'react-native-reanimated'

const AnimatedCircle = Animated.createAnimatedComponent(Circle)

const chartWidth = Layout.window.width
const chartHeight = chartWidth / 2.6
const timing = 200

export default function Chart () {
  const x = useSharedValue(chartWidth / 2)
  const y = useSharedValue(chartHeight / 2)
  // const [val, setVal] = React.useState('happy')
  const gestureHandler = useAnimatedGestureHandler({
    onActive: event => {
      x.value = event.x
      y.value = event.y
    }
  })

  const animatedCircleProps = useAnimatedProps(() => ({
    cx: x.value,
    cy: y.value
  }))

  return (
    <View style={styles.container}>
      <Text>Some Text</Text>
      <View style={styles.chartWrapper}>
        <TapGestureHandler
          onHandlerStateChange={event => {
            x.value = withTiming(event.nativeEvent.x, {
              duration: timing,
              easing: Easing.ease
            })
            y.value = withTiming(event.nativeEvent.y, {
              duration: timing,
              easing: Easing.ease
            })
          }}
        >
          <Animated.View style={styles.box}>
            <PanGestureHandler onGestureEvent={gestureHandler}>
              <Animated.View style={styles.box}>
                <Svg
                  width={chartWidth   10}
                  height={chartHeight   10}
                  viewBox={`0 0 ${chartWidth} ${chartHeight}`}
                  fill='none'
                >
                  <AnimatedCircle
                    animatedProps={animatedCircleProps}
                    r='7'
                    fill='white'
                  />
                  {Array(5)
                    .fill(1)
                    .map((_, index) => (
                      <Line
                        key={index}
                        x2={chartWidth}
                        y2={(chartHeight * index) / 4}
                        y1={(chartHeight * index) / 4}
                        stroke='rgba(255,255,255,0.4)'
                      />
                    ))}
                </Svg>
              </Animated.View>
            </PanGestureHandler>
          </Animated.View>
        </TapGestureHandler>
      </View>
    </View>
  )
}

const styles = StyleSheet.create({
  container: {
    flexDirection: 'column'
  },
  headline: {
    fontSize: 36
  },
  chartWrapper: {
    width: chartWidth   10,
    height: chartHeight   10
  },
  box: {}
})
 

Как мне обновить <Text>Some Text</Text> , когда x > 100 ?

Комментарии:

1. Может быть, я думаю, используя useEffect .. и слушайте x активность : вот так useEffect(() => { if ( x > 100) { /// run a function that upadating <Text>Some </Text> }},[x])

Ответ №1:

1. Создайте общее значение

 const animatedText = useSharedValue('Some Text')
    
 

2. Измените значение sharedValue, когда события жестов завершатся и x > 100

 const gestureHandler = useAnimatedGestureHandler({
  onStart: () => { ... },
  onActive: () => { ... },
  onEnd: () => { ... },
  onFinish: (event) => {
    if (event.x > 100) animatedText.value = 'New Text'
  }    
})
 

3. Используйте ретекст из пакета react-native-redash

 <ReText text={animatedText} />
 

Если вы не хотите использовать react-native-redash, посмотрите, как он построен здесь: https://github.com/wcandillon/react-native-redash/blob/fd0b0ddb3b4c10ae88cf1f8a95890c7c5eb3c475/src/ReText.tsx