react-native-shimmer-placeholder
Version:
<h2 align="center"> React Native Shimmer Placeholder </h2> <p align="center"> <a href="https://www.npmjs.com/package/react-native-shimmer-placeholder"><img src="https://img.shields.io/npm/v/react-native-shimmer-placeholder.svg?style=flat-square"></a>
163 lines (150 loc) • 3.93 kB
JavaScript
import React, { PureComponent } from "react";
import { Animated, Platform, StyleSheet, View } from "react-native";
const getOutputRange = (width, isReversed) =>
isReversed ? [width, -width] : [-width, width];
class ShimmerPlaceholder extends PureComponent {
state = {
beginShimmerPosition: new Animated.Value(-1),
};
getAnimated = () => {
const { delay, duration, isInteraction } = this.props;
return Animated.loop(
Animated.timing(this.state.beginShimmerPosition, {
toValue: 1,
delay,
duration,
useNativeDriver: Platform.OS !== "web",
isInteraction,
})
);
};
animatedValue = this.getAnimated();
render() {
return (
<BasedShimmerPlaceholder
{...this.props}
animatedValue={this.animatedValue}
beginShimmerPosition={this.state.beginShimmerPosition}
/>
);
}
}
ShimmerPlaceholder.defaultProps = {
delay: 0,
duration: 1000,
isInteraction: true,
};
const BasedShimmerPlaceholder = (props) => {
const {
width = 200,
height = 15,
shimmerColors = ["#ebebeb", "#c5c5c5", "#ebebeb"],
isReversed = false,
stopAutoRun = false,
visible,
location = [0.3, 0.5, 0.7],
style,
contentStyle,
shimmerStyle,
LinearGradient = View,
children,
animatedValue,
beginShimmerPosition,
shimmerWidthPercent = 1,
containerProps,
shimmerContainerProps,
childrenContainerProps,
} = props;
const linearTranslate = beginShimmerPosition.interpolate({
inputRange: [-1, 1],
outputRange: getOutputRange(width, isReversed),
});
React.useEffect(() => {
if (!stopAutoRun) {
animatedValue.start();
}
return () => {
animatedValue.stop();
};
}, [stopAutoRun]);
React.useEffect(() => {
if (visible) {
animatedValue.stop();
}
if (!visible && !stopAutoRun) {
animatedValue.start();
}
}, [visible, stopAutoRun]);
return (
<View
style={[
!visible && { height, width },
styles.container,
!visible && shimmerStyle,
style,
]}
{...containerProps}
>
{/* Force render children to restrict rendering twice */}
<View
style={[
!visible && { width: 0, height: 0, opacity: 0 },
visible && contentStyle,
]}
{...childrenContainerProps}
>
{children}
</View>
{!visible && (
<View
style={{ flex: 1, backgroundColor: shimmerColors[0] }}
{...shimmerContainerProps}
>
<Animated.View
style={{ flex: 1, transform: [{ translateX: linearTranslate }] }}
>
<LinearGradient
colors={shimmerColors}
style={{ flex: 1, width: width * shimmerWidthPercent }}
start={{
x: -1,
y: 0.5,
}}
end={{
x: 2,
y: 0.5,
}}
locations={location}
/>
</Animated.View>
</View>
)}
</View>
);
};
const styles = StyleSheet.create({
container: {
overflow: "hidden",
},
});
/**
* To create ShimmerPlaceholder by Linear Gradient. Only useful when you use 3rd party,
* For example: react-native-linear-gradient
* @param {Linear Gradient Component} LinearGradient - 'expo-linear-gradient' by default
*
* @example
*
* import LinearGradient from 'react-native-linear-gradient';
* import { createShimmerPlaceholder } from 'react-native-shimmer-placeholder'
*
* const ShimmerPlaceHolder = createShimmerPlaceholder(LinearGradient)
*
* ...
*
* <ShimmerPlaceHolder />
*/
export const createShimmerPlaceholder = (LinearGradient = View) =>
React.forwardRef((props, ref) => (
<ShimmerPlaceholder LinearGradient={LinearGradient} ref={ref} {...props} />
));
export default ShimmerPlaceholder;