在 React Native Expo 中创建动画能量流线

问题描述 投票:0回答:1

我目前正在使用 Expo 开发一个 React Native 应用程序,我面临着在我的一个屏幕上实现动画能量流线的挑战。目标是对房屋图像上的线条进行动画处理以模拟能量流动,如以下概念所示:

我目前拥有的:

enter image description here

应该是什么样子:

enter image description here

我探索了各种选项,但还没有找到合适的库或方法来在 React Native 中实现这种效果。虽然我预计动画本身不会过于复杂,但我对 React Native 中的动画相对较新,并且可以使用一些关于如何有效完成此任务的指导。

这是我迄今为止尝试过的:

搜索提供类似动画功能的现有库。 在React Native中尝试了基本的动画技术,但没有达到预期的效果。 如果有人有在 React Native 中创建这样的动画效果的经验或见解,我将非常感谢您对如何继续进行的帮助或指导。

提前感谢您的帮助!

react-native expo android-animation ios-animations
1个回答
0
投票

所以我做了一个组件:

import React, { useState, useEffect } from 'react';
import { View, Animated, Easing, StyleSheet } from 'react-native';

const EnergyFlowAnimation = ({ duration = 1000, direction = 'left', style = null, value = 1, nrOfMarks = 5 }) => {
    const [arrowPosition] = useState(new Animated.Value(0));

    const animation = Animated.timing(arrowPosition, {
        toValue: value,
        duration: duration,
        easing: Easing.linear,
        // easing: Easing.back(),
        useNativeDriver: true,
    });

    const startAnimation = () => {
        animation.start(() => {
            animation.reset();
            startAnimation();
        });
    };

    useEffect(() => {
        startAnimation();
    }, []);

    const Mark = () => {
        return (
            <View style={{
                width: 7,
                height: 5,
                backgroundColor: '#FF6B00',
                marginLeft: 3,
                borderRadius: 5
            }} />
        );
    }

    let arrowTranslateX = 0;
    let arrowTranslateY = 0;
    let arrowRotation = '0deg';

    switch (direction) {
        case 'left':
            arrowTranslateX = arrowPosition.interpolate({
                inputRange: [0, 1],
                outputRange: [40, -10],
            });
            arrowRotation = '180deg';
            break;
        case 'right':
            arrowTranslateX = arrowPosition.interpolate({
                inputRange: [0, 1],
                outputRange: [-10, 40],
            });
            arrowRotation = '0deg';
            break;
        case 'top':
            arrowTranslateY = arrowPosition.interpolate({
                inputRange: [0, 1],
                outputRange: [40, -10],
            });
            arrowRotation = '-90deg';
            break;
        case 'down':
            arrowTranslateY = arrowPosition.interpolate({
                inputRange: [0, 1],
                outputRange: [-10, 40],
            });
            arrowRotation = '90deg';
            break;
        default:
            arrowTranslateX = arrowPosition.interpolate({
                inputRange: [0, 1],
                outputRange: [40, -10],
            });
    }

    return (
        <View>
            <Animated.View
                style={[
                    styles.roadLine, style,
                    {
                        transform: [{ translateX: arrowTranslateX }, { translateY: arrowTranslateY }, { rotate: arrowRotation }],
                        // position: 'absolute',
                        justifyContent: 'center',
                        alignItems: 'center',
                        alignSelf: 'center',
                    }]}>
                {[...new Array(nrOfMarks)].map((_, index) => <View key={index}><Mark /></View>)}
            </Animated.View>
        </View>
    );
};

const styles = StyleSheet.create({
    roadLine: {
        height: 10,
        flexDirection: 'row',
    },
});

export default EnergyFlowAnimation;

我将该组件称为如下:

<View style={[styles.bottom, { top: 20, flexDirection: 'row' }]} >
                <View
                    style={{
                        backgroundColor: 'blue',
                        width: 20,
                        height: 20,
                        zIndex: 1,
                        right: -10
                    }}
                />
                <EnergyFlowAnimation
                    duration={500}
                    direction='right'
                    value={0.6}
                    nrOfMarks={15}
                />
                <View
                    style={{
                        backgroundColor: 'yellow',
                        width: 20,
                        height: 20,
                        right: 2
                    }}
                />

            </View>

这给了我以下内容:

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.