React Native custom loader Animation from CSS code

Viewed 468

I'm having a problem recreating a CSS loader animation in React Native with Animated API.

My React Native attempt: screen record.

CSS code is below:

.whitePillar {
    width: 8px;
    height: 50px;
    margin-right:5px;
    background-color: #FFF;
    animation: animation 1s infinite;
    float: left;
}

.whitePillar :nth-child(10) {
    animation-delay: 0.9s;  
}
.whitePillar :nth-child(9){
    -webkit-animation-delay: 0.8s;
    animation-delay: 0.8s;  
}   
.whitePillar :nth-child(8) {
    animation-delay: 0.7s;  
}
.whitePillar :nth-child(7){
    -webkit-animation-delay: 0.6s;
    animation-delay: 0.6s;  
}
.whitePillar :nth-child(6) {
    animation-delay: 0.5s;  
}
.whitePillar :nth-child(5) {
    animation-delay: 0.4s;
}
.whitePillar :nth-child(4){
    -webkit-animation-delay: 0.3s;
    animation-delay: 0.3s;      
}
.whitePillar :nth-child(3) {
    animation-delay: 0.2s;  
}
.whitePillar :nth-child(2) {
    animation-delay: 0.1s;
}

@keyframes animation {
    50% {
        transform: translateX(-25px) scaleY(0.5);
    }

}

React Native code is below:

<View style={styles.loaderContainer}>
      <View style={styles.pillarsWrapper}>
             {[...Array(numberOfPillars)].map((value, index) => (
                   <LoaderPillar
                        delay={index*100}
                        key={index}
                   />
              ))}
      </View>
</View>

LoaderPillar represents every individual white pillar:

<Animated.View
    style={[styles.pillar, pillarAnimation]}
 />

and I've done the animation on LoaderPillar using this:

const [ pillarAnimationTranslate ] = useState(new Animated.Value(0));
const [ pillarAnimationScale ] = useState(new Animated.Value(1));

const pillarAnimation = {
    transform: [{translateX: pillarAnimationTranslate}, {scaleY: pillarAnimationScale}]
};

useEffect(() => {
    Animated.loop(Animated.timing(pillarAnimationScale, {
        toValue: 0.5,
        duration: 500,
        delay: delay,
        useNativeDriver: true,
        easing: Easing.ease
    })).start();
}, [pillarAnimationScale]);

useEffect(() => {
    Animated.loop(Animated.timing(pillarAnimationTranslate, {
        toValue: -25,
        duration: 500,
        delay: delay,
        useNativeDriver: true,
        easing: Easing.ease
    })).start()

}, [pillarAnimationTranslate]);

I am new to React Native animations, so I don't even know if I'm on the right track. The problem, I think, is the keyframes part in CSS - that percentage (50%) - and I don't know how would I recreate that. Any advices on upgrading this or even completely changing would be greatly appreciated. Thank You in advance.

1 Answers

EDIT: still NOT working, but very close to the end result. I broke down this problem into two parts: first making scale animation and then just adding translate animation - it is easier that way.

Code:

const [ pillarAnimationTranslate ] = useState(new Animated.Value(0));

Animated.loop(
    Animated.sequence([
        Animated.timing(
            pillarAnimationScale,
            {
                toValue: 1,
                duration: 500,
                delay: delay,
                useNativeDriver: true,
                easing: Easing.ease
            }
        ),
        Animated.timing(
            pillarAnimationScale,
            {
                toValue: 0,
                duration: 500,
                useNativeDriver: true
            })
        ])
).start();

And then using interpolate function:

const scale = pillarAnimationScale.interpolate({
    inputRange: [0, 1],
    outputRange: [1, 0.5]
});

const pillarAnimation = {
    transform: [{scaleY: scale}]
};

And in the ned returning Animated View (as in the original post);

return (
    < Animated.View
        style={[styles.pillar, pillarAnimation]}
    />
);

The problem I'm now having is inconsistency of the iterations, as you can see in the GIF below (first iteration is perfect and then it just gets chaotic for some reason, it should be a perfect wave at all times):

enter image description here

Does anybody see what is causing inconsistent iterations?

Related