#javascript #reactjs #react-native #expo #react-animated
Вопрос:
Я очень новичок в родной реакции и столкнулся с проблемой, которая возникает, когда я хочу анимировать цвет оттенка изображения. Я ожидаю, что цвет будет постепенно меняться с течением времени, как анимированный.Время должно быть выбрано, но вместо этого он делает только первый кадр анимации, а затем зависает. Однако по какой-то причине, когда я просто меняю «Цвет оттенка» на «Цвет фона», анимация работает нормально.
Вот мой код:
import React from 'react';
import { useState } from 'react';
import { Text, View, TouchableHighlight, Dimensions, Component, Image, Animated } from 'react-native';
import PropTypes from 'prop-types';
function RGBtoCSS(rgb) {
return "rgb(" rgb[0] "," rgb[1] "," rgb[2] ")";
}
class MyImage extends React.Component {
constructor(props) {
super(props);
this.anim = new Animated.Value(0);
this.animate();
}
animate() {
this.props.onPress();
Animated.timing(
this.anim,
{
toValue: 1,
duration: 500,
useNativeDriver: false
}
).start();
}
render() {
var style = {
width: 500,
height: 500,
resizeMode: 'stretch'
};
var col = this.anim.interpolate(
{
inputRange: [0, 1],
outputRange: [RGBtoCSS([0, 0, 0]), RGBtoCSS([140, 74, 140])]
});
return (
<Animated.Image source={this.props.img} style={{ ...style, tintColor: col }} />
);
}
}
MyImage.propTypes = { img: PropTypes.string.isRequired, onPress: PropTypes.func.isRequired, spacing: PropTypes.number.isRequired };
export default function App() {
return (
<View style={{
flex: 1,
backgroundColor: RGBtoCSS([255, 255, 255])
}}>
<MyImage img={{ uri: 'https://img.icons8.com/color/452/google-logo.png' }} onPress={() => { }} spacing={0} />
</View>
);
}
(демо доступно по адресу https://snack.expo.dev/v0GeiLbOP)
Комментарии:
1. Похоже
tintColor
, это не поддается оживлению.2. есть ли оживляемая альтернатива?
3. вы пытались зарегистрировать
RGBtoCSS
функцию, чтобы увидеть, какие значения вычисляются? Возможно,interpolate
это не очень хорошо работает с вашей функцией.4. это прекрасно работает с фоновым цветом, так что я не думаю, что в этом проблема
5. и я уже пробовал это
Ответ №1:
Я нашел обходной путь для этого. Вы можете сложить два <Animated.Image>
изображения друг на друга, причем 1-е изображение имеет окончательный цвет, а 2-е изображение-начальный цвет. Затем вы можете использовать opacity
для создания эффекта затухания между этими двумя изображениями, который также хорошо работает interpolate
.
import React from 'react';
import { useState } from 'react';
import { Text, View, TouchableHighlight, Dimensions, Component, Image, Animated } from 'react-native';
import PropTypes from 'prop-types';
function RGBtoCSS(rgb) {
return "rgb(" rgb[0] "," rgb[1] "," rgb[2] ")";
}
class MyImage extends React.Component {
constructor(props) {
super(props);
this.anim = new Animated.Value(0);
this.animate();
}
animate() {
this.props.onPress();
console.log(this.anim)
Animated.timing(
this.anim,
{
toValue: 1,
duration: 500,
useNativeDriver: false
}
).start();
}
render() {
var style = {
width: 500,
height: 500,
resizeMode: 'stretch'
};
var col = this.anim.interpolate(
{
inputRange: [0, 1],
outputRange: [1, 0]
});
return (
<View>
<Animated.Image source={this.props.img} style={{ ...style,tintColor: RGBtoCSS([140, 74, 140]) }} />
<Animated.Image source={this.props.img} style={{ ...style, opacity:col, transform:[{translateY:"-100%"}], tintColor: RGBtoCSS([0, 0, 0]) }} />
</View>
);
}
}
MyImage.propTypes = { img: PropTypes.string.isRequired, onPress: PropTypes.func.isRequired, spacing: PropTypes.number.isRequired };
export default function App() {
return (
<View style={{
flex: 1,
backgroundColor: RGBtoCSS([255, 255, 255])
}}>
<MyImage img={{ uri: 'https://img.icons8.com/color/452/google-logo.png' }} onPress={() => { }} spacing={0} />
</View>
);
}
Закуска — https://snack.expo.dev/ZYulbKh3g