Я пытаюсь создать компонент, используя Animated на React Native, где круг расширяется от точки печати, чтобы охватить весь экран.
Идея состоит в том, что, по сути, существует карусель цветов, скажем:
const colors = ['white', 'black', 'green', 'blue', 'red', 'pink'];
Вы начинаете с цвета 0 в качестве фона, а затем, когда вы нажимаете на экран, круг цвета 1 расширяется (из ничего) от точки нажатия и занимает весь экран,В этот момент, когда анимация завершена, colorIndex
увеличивается, и анимированный круг одновременно стирается, так что мы плавно перешли к следующему цвету, который теперь является фоном.(Например, теперь цвет фона «черный»).
Затем, когда вы нажимаете снова, процесс повторяется, расширяя круг «зеленого», чтобы заполнить экран, затем обновляя зеленый, чтобы быть цветом BG, и т. Д.
(Чтобы уточнить, чтоЯ ищу в анимации, отметьте этот GIF (без значков и т. Д.)).
Я пытаюсь сделать это с помощью Animated, и код, подобный следующему, вызываетсянажатие основного фонового компонента (TouchableHighlight):
triggerSwipe(event) {
this.setState({ location: { x: event.nativeEvent.locationX, y: event.nativeEvent.locationY } });
Animated.timing(
this.state.diameter,
{ toValue: Dimensions.get('window').height * 2, duration: 500 },
).start(() => {
this.state.diameter.setValue(0);
this.setState({ colorIndex: this.state.colorIndex + 1 });
});
}
Тогда идея состоит в том, чтобы в функции render
я установил left
и top
моего absolute
только расположенного компонента кругаравное местоположение, и я устанавливаю width
и height
равными diameter
, а также borderRadius
(diameter / 2.0
не будет работать, потому что diameter
является Анимированным объектом, а не числом).
Здесь происходит две проблемы, которые я не могу понять (обе они видны в GIF, включенном в нижней части этого вопроса):
- Есть черныймигать перед каждой анимацией.Он охватывает весь компонент TouchableHighlight.И всегда черный.Какого бы цвета я ни был.В компоненте отсутствует черный код (!).
- Местоположение определяет край круга (или, точнее, квадрат, внутри которого он транскрибируется), а не центр.Я хочу, чтобы он определил центр круга, чтобы круг расширялся наружу от моего пресса.
Я предполагаю, что № 1 действительно трудно рассуждать без всего кода.Поэтому я вставлю полный код компонента ниже.Второй, я надеюсь, немного более концептуален / его легко понять, не играя с ним.
Кто-нибудь может придумать хороший способ установить местоположение центра круга?Я обеспокоен тем, что требуется постоянное обновление левого / верхнего положения круга в зависимости от его диаметра (left: location.x - diameter._value / 2
), что избавит меня от всех преимуществ производительности Animated, насколько я понимаю.Есть идеи получше?
Вот полный код компонента:
import React from 'react';
import { TouchableHighlight, Animated } from 'react-native';
import { Dimensions } from 'react-native';
const colors = ['white', 'black', 'green', 'blue', 'red', 'pink'];
const color = index => colors[index % colors.length];
class ColorScape extends React.Component {
constructor(props) {
super(props);
this.state = {
colorIndex: 0,
location: { x: 0, y: 0 },
diameter: new Animated.Value(0)
};
}
triggerSwipe(event) {
this.setState({ location: { x: event.nativeEvent.locationX, y: event.nativeEvent.locationY } });
Animated.timing(
this.state.diameter,
{ toValue: Dimensions.get('window').height * 2, duration: 500 },
).start(() => {
this.state.diameter.setValue(0);
this.setState({ colorIndex: this.state.colorIndex + 1 });
});
}
render() {
const { colorIndex, diameter, location } = this.state;
const circleStyles = {
backgroundColor: color(colorIndex + 1),
width: diameter,
height: diameter,
borderRadius: diameter,
position: 'absolute',
zIndex: 2,
left: location.x,
top: location.y
};
return (
<TouchableHighlight
style={ {
flex: 1,
width: '100%',
height: '100%',
zIndex: 1,
backgroundColor: color(colorIndex)
} }
onPress={ (event) => this.triggerSwipe(event) }
>
<Animated.View
style={ circleStyles }
/>
</TouchableHighlight>
);
}
}
export default ColorScape;
Вот текущая функциональность (в симуляторе iPhone X):