0

我正在尝试创建一个调整大小的按钮(按下时会变小一点)。我使用 TouchableWithoutFeedbackreact-native-gesture-handler并使用react-native-reanimated.

到目前为止,这是我的代码:

import React, { useState } from 'react';
import { View } from 'react-native';
import Animated, { Easing, Extrapolate } from 'react-native-reanimated';
import { TouchableWithoutFeedback } from 'react-native-gesture-handler';

const { interpolate, sub } = Animated;

const TouchableResize = (props) => {
  const { onPress, children } = props;
  const [scale, setScale] = useState(0);
  const scaling = interpolate(scale, {
    inputRange: [0, 1],
    outputRange: [1, 0.90],
    extrapolate: Extrapolate.CLAMP
  });
  return (
    <TouchableWithoutFeedback onPressIn={() => setScale(1)} onPressOut={() => setScale(0)}>
      <Animated.View style={{ transform: [{ scaleX: scaling }, { scaleY: scaling }] }}>
        {children}
      </Animated.View>
    </TouchableWithoutFeedback>
  );
};

export { TouchableResize };

此代码部分有效。按下按钮时,按钮大小调整为 0.90,但动画不流畅。它直接捕捉到 0.90,当它释放时,按钮直接捕捉回来。

如何更新我的代码以使动画顺利运行?请注意,我是 react-native-reanimated 的完整初学者。

4

1 回答 1

3

你必须使用timing函数来改变你Animated.Value的时间。这里是docs中的示例。另外,我创建了世博小吃示例。这里更新了组件代码

import React, { useState, useMemo } from 'react';
import { View } from 'react-native';
import Animated, { Easing, Extrapolate } from 'react-native-reanimated';
import { TouchableWithoutFeedback } from 'react-native-gesture-handler';

const {
  Clock,
  Value,
  set,
  cond,
  startClock,
  clockRunning,
  timing,
  debug,
  stopClock,
  block,
  interpolate,
  useCode,
} = Animated;

function runTiming(clock, from, to) {
  const state = {
    finished: new Value(0),
    position: new Value(from),
    time: new Value(0),
    frameTime: new Value(0),
  };

  const config = {
    duration: 100,
    toValue: new Value(to),
    easing: Easing.inOut(Easing.ease),
  };

  return block([
    cond(
      clockRunning(clock),
      [],
      startClock(clock),
    ),
    // we run the step here that is going to update position
    timing(clock, state, config),
    // if the animation is over we stop the clock
    cond(state.finished, debug('stop clock', stopClock(clock))),
    // we made the block return the updated position
    state.position,
  ]);
}


const TouchableResize = (props) => {
  const { onPress, children } = props;
  const [pressed, setPressed] = useState(false);
  const {clock, scale} = useMemo(() => ({
    clock: new Clock(),
    scale: new Value(1), 
  }), [])

  useCode(
    () => block([
      pressed ? set(scale, runTiming(clock, 0, 1)) : set(scale, runTiming(clock, 1, 0))
    ]), [pressed]
  );

  const scaling = interpolate(scale, {
    inputRange: [0, 1],
    outputRange: [1, 0.90],
    extrapolate: Extrapolate.CLAMP
  });
  return (
    <TouchableWithoutFeedback onPressIn={() => setPressed(true)} onPressOut={() => setPressed(false)}>
      <Animated.View style={{ transform: [{ scaleX: scaling }, { scaleY: scaling }] }}>
        {children}
      </Animated.View>
    </TouchableWithoutFeedback>
  );
};

export { TouchableResize };
于 2020-06-10T09:26:29.043 回答