在React Native中设置背景颜色动画

Animating backgroundColor in React Native

本文关键字:背景 颜色 动画 设置 React Native      更新时间:2023-09-26

如何在React Native中设置从一种颜色到另一种颜色的动画。我发现,通过插值一个动画.值,你可以动画颜色通过:

var BLACK = 0;
var RED = 1;
var BLUE = 2;
backgroundColor: this.state.color.interpolate({
  inputRange: [BLACK, RED, BLUE],
  outputRange: ['rgb(0, 0, 0)', 'rgb(255, 0, 0)', 'rgb(0, 0, 255)']
})

Animated.timing(this.state.color, {toValue: RED}).start();

但使用这种方法,从黑色到蓝色,你必须经过红色。在混合中添加更多的颜色,你最终会进入20世纪80年代的迪斯科舞厅。

有没有其他方法可以让你直接从一种颜色变成另一种颜色?

如果你有Animated.Value,比如说x,你可以像这样插值颜色:

render() {
    var color = this.state.x.interpolate({
        inputRange: [0, 300],
        outputRange: ['rgba(255, 0, 0, 1)', 'rgba(0, 255, 0, 1)']
    });
    return (
        <Animated.View style={{backgroundColor:color}}></Animated.View>
    );
}

你可以在我发布在github上的问题中找到完整的工作示例。

如果你能在按下按钮的那一刻获得动画颜色值的颜色,那么你可能会这样做

var currentColor = ? : 
this.state.color = 0; 
var bgColor = this.state.color.interpolate({
  inputRange: [0, 1],
  outputRange: [currentColor, targetColor]
});

因此,您可以为每个按钮设置不同的targetColor。

我在这里创建了一个示例,说明如何使用最新版本的react native实现这一点。

https://cjoshmartin.com/blog/react-native-animations-example/

您也可以在此处阅读更多信息:https://www.codedaily.io/courses/Master-React-Native-Animations/Color-Background-Colorhttps://reactnative.dev/docs/animations

我做了一个钩子来做大卫·舒曼告诉我的事。

useColorAnimation.js

import { useRef, DependencyList, useMemo, useEffect, useState } from "react";
import { Animated } from "react-native";
const useColorAnimation = (color) => {
  const anim = useMemo(() => new Animated.Value(0), [color]);
  const [finished, setFinished] = useState(true)
  const currentColor = useRef(color);
  const nextColor = useMemo(()=> color, [color]);
  const animColor = anim.interpolate({
    inputRange: [0, 1],
    outputRange: [currentColor.current, nextColor],
  });
  useEffect(() => {
    setFinished(false)
    Animated.spring(anim, {
      toValue: 1,
      useNativeDriver: false,
    }).start(() => {
      currentColor.current = nextColor;
      setFinished(true)
    });
  }, [color]);
  return [animColor, finished];
};
export default useColorAnimation

使用挂钩:

import React, { useState } from 'react';
import { StyleSheet, Animated, Button } from 'react-native';
import useColorAnimation from './useColorAnimation';
const colors = ['rgb(0, 0, 0)', 'rgb(255, 0, 0)', 'rgb(0, 0, 255)'];
const getNextColor = (currentColor) => {
  const index = colors.indexOf(currentColor) + 1;
  return index == colors.length ? colors[0] : colors[index];
};
export default function App() {
  const [color, setColor] = useState(colors[0]);
  const [backgroundColor, finished] = useColorAnimation(color);
  const handleButton = () => setColor((current) => getNextColor(current));
  return (
    <Animated.View style={[styles.container, { backgroundColor }]}>
      <Button title="Next" onPress={handleButton} disabled={!finished} />
    </Animated.View>
  );
}
const styles = StyleSheet.create({
  container: {
    justifyContent: 'center',
    alignItems: 'center',
    flex: 1,
  },
});

这里有一个例子https://snack.expo.dev/@rafaelsantos/粗羊角面包

在循环中通过复制末尾的第一种颜色来阻止我的闪烁:

  const backgroundColourIndex = useRef(new Animated.Value(0)).current;
  let backgroundColorAnimated = backgroundColourIndex.interpolate({
    inputRange: [0, 1, 2, 3],
    outputRange: ['red', 'blue', 'yellow', 'red'],
  });

对于颜色等非数值,您也可以分步插值,如下所示:

<Animated.Text
  style={{
    color: colorAnim.interpolate({
      inputRange: [0, 0.5, 1],
      outputRange: ['black', 'gray', 'white']
  })
}}>
const animatedBkg = interpolate(scale, {
  inputRange: [0, 150],
  outputRange: [Animated.color(242, 81, 48), Animated.color(0,0,0)],
  // extrapolate: Extrapolate.CLAMP,
})

用复活的测试。

使用setValue和state来控制开始和结束颜色。