Я пытаюсь превратить класс в функцию. Это в основном потому, что если я смогу заставить его работать, я хочу использовать его для изучения различных анимаций, у меня был некоторый успех, но не на 100%. Первоначально он отображал значок, который при нажатии вращался в одну сторону, а при повторном нажатии - в другую. Что я пытался сделать, так это избавиться от значка и заменить его изображением. Он работает при нажатии один раз, но затем ничего не делает.
Я борюсь с переключаемым аспектом этого и устанавливаю состояние, которое я думаю, потому что я не могу правильно настроить его в функции.
Я пробовал несколько вещей, но это лучшее, что я могу получить. Если я покажу исходный код, а затем то, что мне удалось изменить, возможно, кто-то сможет указать мне правильное направление относительно того, что я делаю неправильно.
Все, что я хочу, это изображение, которое отображается, а затем при нажатии вращается вправо, а затем, если щелкнуть снова, оно вращается влево.
Я делаю это, чтобы повозиться с настройками и, надеюсь, немного лучше изучить анимацию.
Любая помощь будет принята с благодарностью.
Оригинальный код:
import React from 'react';
import { View, StyleSheet, Animated, Image, TouchableOpacity } from 'react-native';
import { Ionicons } from '@expo/vector-icons';
const TabIcon = ({
onPress,
menuToggled
}) => {
const logoStyles = [styles.logoStyle];
if (menuToggled !== null) {
const animation = new Animated.Value(menuToggled ? 0 : 1);
Animated.timing(animation, {
toValue: menuToggled ? 1 : 0,
duration: 500,
useNativeDriver: true
}).start();
const rotateInterpolate = animation.interpolate({
inputRange: [0, 1],
outputRange: ['0deg', '360deg']
});
const animatedStyles = { transform: [{ rotate: rotateInterpolate }] };
logoStyles.push(animatedStyles);
}
return (
<TouchableOpacity
style = {styles.tabStyle}
onPress = {onPress}
>
<Animated.View style = {logoStyles}>
<Animated.Image
style = {styles.tinyLogo}
source = {{
uri: 'https://reactnative.dev/img/tiny_logo.png',
}}
/></Animated.View>
</TouchableOpacity>
);
};
export default class App extends React.Component {
state = {
menuToggled: null
}
toggleMenu = () => {
this.setState(prevState => {
return { menuToggled: !prevState.menuToggled };
});
}
render () {
return (
<View style = {styles.container}>
<TabIcon
onPress = {this.toggleMenu}
menuToggled = {this.state.menuToggled}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'white'
},
tinyLogo: {
width: 150,
height: 150,
borderRadius: 100,
margin: 8,
},
});
и что я изменил до сих пор:
import React, { useRef, useState } from "react";
import { View, StyleSheet, Animated, Image, TouchableOpacity, Easing } from 'react-native';
import Constants from 'expo-constants';
const App = () => {
const spinValue = useRef(new Animated.Value(0)).current;
const [menuToggled, setMenuToggled] = useState([null]);
toggleMenu = () => {
setMenuToggled(menuToggled === "null" ? "menuToggled" : "null");
}
const Spinner = ({
onPress,
menuToggled
}) => {
const logoStyles = [styles.logoStyle];
const animation = new Animated.Value(0);
const go = () => {
Animated.timing(animation, {
toValue: 1,
duration: 1500,
easing: Easing.elastic(1),
useNativeDriver: true
}).start();
}
const rotateInterpolate = animation.interpolate({
inputRange: [0, 1],
outputRange: ['0deg', '360deg']
});
const animatedStyles = { transform: [{ rotate: rotateInterpolate }] };
logoStyles.push(animatedStyles);
return (
<TouchableOpacity
onPress = {go}
>
<Animated.View style = {logoStyles}>
<Animated.Image
style = {styles.tinyLogo}
source = {{
uri: 'https://reactnative.dev/img/tiny_logo.png',
}}
/></Animated.View>
</TouchableOpacity>
);
};
return (
<View style = {styles.container}>
<Spinner
onPress = {toggleMenu}
menuToggled = {menuToggled}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'white'
},
tinyLogo: {
width: 150,
height: 150,
borderRadius: 100,
margin: 8,
},
});
export default App;
Есть несколько проблем. Сначала вы инициализировали menuToggled как [null]
, когда оно должно было быть null
. Вы также забыли использовать onPress в TabIcon
. Наиболее примечательной вещью было обертывание TabIcon
в useCallback, чтобы предотвратить его постоянное воссоздание. Экспо-закуска:
import React, { useRef, useState, useCallback } from 'react';
import {
View,
StyleSheet,
Animated,
Image,
TouchableOpacity,
} from 'react-native';
import Constants from 'expo-constants';
const App = () => {
const spinValue = useRef(new Animated.Value(0)).current;
const [menuToggled, setMenuToggled] = useState(null);
const TabIcon = useCallback(({ onPress, menuToggled }) => {
const logoStyles = [styles.logoStyle];
// initialized base on menuToggled
// if not done then it will take an additional button press to trigger
// the animation
const animation = useRef(new Animated.Value(menuToggled ? 0 : 1)).current;
const startAnimation = () => {
Animated.timing(animation, {
toValue: menuToggled ? 1 :0,
duration: 500,
useNativeDriver: true,
}).start();
};
const rotateInterpolate = animation.interpolate({
inputRange: [0, 1],
outputRange: ['0deg', '360deg'],
});
const animatedStyles = { transform: [{ rotate: rotateInterpolate }] };
logoStyles.push(animatedStyles);
return (
<TouchableOpacity
onPress = {() => {
startAnimation();
onPress?.();
}}>
<Animated.View style = {logoStyles}>
<Animated.Image
style = {styles.tinyLogo}
source = {{
uri: 'https://reactnative.dev/img/tiny_logo.png',
}}
/>
</Animated.View>
</TouchableOpacity>
);
},[]);
return (
<View style = {styles.container}>
<TabIcon
onPress = {() => setMenuToggled((prev) => !prev)}
menuToggled = {menuToggled}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'white',
},
tinyLogo: {
width: 150,
height: 150,
borderRadius: 100,
margin: 8,
},
});
export default App;
Ты бриллиант, Значит, я не так уж сильно ошибался тогда? Где был обратный вызов в версии класса? И благодарю вас.
В вашем компоненте класса вы создали TabIcon
вне функции рендеринга. Я думаю, что если вы переместите TabIcon
за пределы компонента, вам не понадобится useCallback
Как мне это сделать? Я собирался спросить, возможно ли сделать что-то подобное, чтобы я мог добавить такие вещи к существующим вещам, таким как плоские списки.
Спасибо за это, но он вращается вокруг оси? На этом новом вы переместили TabIcon за пределы рендера?
Я только что заметил, что вращение не по оси, но я думаю, что это потому, что вращается вид, а не само изображение. Чтобы преодолеть это, вы можете просто анимировать само изображение, а не представление. Я также разработал демо-версию флэтлиста snack.expo.dev/pzQokudmP
Вау, спасибо, это потрясающе. Немного дерзко, но я пытаюсь добавить к нему отскок при нажатии, чтобы изображение увеличивалось и возвращалось назад во время вращения. Я задал еще один вопрос по этому поводу, но у вас, возможно, уже была идея, и еще раз спасибо, приятель.
Привет, спасибо за это. Он снова крутит его на оси? Эффект, который я ищу, похож на пульс или сердцебиение. Кроме того, вместо предопределенного изображения, насколько сложно было бы добавить разные изображения, такие как randomuser.me, и информацию о них в плоский список? Я не прошу вас сделать это, просто возможно ли это и как лучше всего двигаться дальше? Спасибо
Я отсортировал вращение по оси следующим образом: const translateX = moveAnimValue.interpolate({ inputRange: [0, 1], outputRange: [0, 1], }); Я с нетерпением жду вашего мнения об этом случайном изображении и профиле! Спасибо
Привет, я добавил эффект, который искал, следующим образом: }); Это то, о чем я говорил, чтобы заставить это работать, чтобы было легче научиться добавлять вещи в анимацию.
Это было бы не слишком сложно. данные будут созданы с помощью хука useState
и инициализированы пустым массивом. Затем при монтировании компонента вы должны получить данные от случайного пользователя, отформатировать их по мере необходимости, а затем установить для них данные.
Это блестяще, приятель, но я имел в виду создание изображений, предоставленных случайным пользователем, в качестве кликабельного значка. Вы очень талантливы и спасибо за вашу помощь
Для этого вам нужно будет SpinButton
принять исходную опору. Затем в компоненте Item
вам нужно будет иметь свойство изображений и создать часть состояния для хранения индекса изображения. При нажатии кнопки вы устанавливаете индекс изображения на случайное число от 0 до images.length. Затем установите исходную опору на images[imageIndex]
Вау еще раз, спасибо, приятель, мне пришлось вынуть setImageIndex(getRandomInt(0, images.length)); в противном случае он изменил изображение после первого вращения. Я собираюсь попробовать использовать это, чтобы посмотреть, смогу ли я добавить их в этот проект здесь: github.com/catalinmiron/react-native-movie-2.0-carousel Прежде чем я это сделаю, я столкнусь со многими проблемами, и так ли это? возможный? Также я хотел бы в конечном итоге анимировать несколько других элементов, но не уверен, следует ли мне использовать reanimated или LayoutAnimation. Вот где я путаюсь между 3! еще раз спасибо
Я ничего не знаю об анимации макета, но я определенно предпочитаю reanimated анимационной библиотеке RN. Я просматриваю проект, но я действительно не понимаю, почему вы не можете добавить то, что у вас есть.
Привет, я хочу использовать это, потому что я хочу добавить анимацию к изображению профиля, а затем к общему макету, как это dribbble.com/shots/8257559-Movie-2-0 Если я смогу научиться делать что-то подобное или изучить код, который работает, тогда я был бы счастливым человеком. Если вы посмотрите на это, как лучше всего подойти к такому проекту. Также мы используем анимированные на этом не реанимированном. В чем разница и будет ли это иметь какое-либо значение для текущего проекта, и легко ли его изменить? спасибо аган
Я думаю, что реанимация построена поверх реактивной реанимации. По умолчанию каждая анимация использует собственный драйвер, и значения анимации не нужно оборачивать в useRef
. Я уверен, что есть еще что-то, но мне нравится внешний вид и легкость реанимации. Преобразование в реанимацию может потребовать больше усилий и, вероятно, не стоит затраченных усилий. Кроме того, вероятно, лучше хотя бы быть знакомым с нативным анимированным API реакции.
Давайте продолжим обсуждение в чате.
Привет, PhantomSpooks, не могли бы вы взглянуть на stackoverflow.com/questions/75152867/… пожалуйста. Я как бы разобрался с анимацией, но не могу включить ее в FlatList, как вы.
Похоже, вы пытаетесь повернуть значок в навигаторе панели вкладок. Я не уверен, что компонент
TabIcon
хорошо свяжется с навигатором. Если это не даст мне знать