VbeSkeleton.js 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. import React, { useEffect, useRef } from 'react';
  2. import { Animated, Easing, View } from 'react-native';
  3. const VbeSkeleton = ({
  4. style,
  5. color="rgba(0, 10, 20, 0.1)",
  6. layout=[],
  7. widthList=["100%"],
  8. height=16,
  9. margin={},
  10. borderRadius=8,
  11. animate=true
  12. }) => {
  13. const opacity = useRef(new Animated.Value(1)).current;
  14. useEffect(() => {
  15. if (animate) {
  16. startScanAnimate()
  17. }
  18. }, [animate])
  19. const startScanAnimate = () => {
  20. Animated.timing(opacity, {
  21. toValue: 0.1,
  22. duration: 1000,
  23. easing: Easing.linear,
  24. useNativeDriver: true
  25. }).start(() => {
  26. if (animate) {
  27. endScanAnimate();
  28. }
  29. });
  30. }
  31. const endScanAnimate = () => {
  32. Animated.timing(opacity, {
  33. delay: 200,
  34. toValue: 1,
  35. duration: 1000,
  36. easing: Easing.linear,
  37. useNativeDriver: true
  38. }).start(() => {
  39. if (animate) {
  40. startScanAnimate();
  41. }
  42. });
  43. }
  44. if (layout.length > 0) {
  45. return (
  46. <Animated.View style={[style, {opacity}]}>
  47. { layout.map((item, index) =>
  48. <View key={index} style={{height, borderRadius: borderRadius, backgroundColor: color, ...item}}>
  49. </View>
  50. )}
  51. </Animated.View>
  52. )
  53. } else {
  54. return (
  55. <Animated.View style={[style, {opacity}]}>
  56. { widthList.map((item, index) =>
  57. <View key={index} style={{width: item, height, ...margin, borderRadius: borderRadius, backgroundColor: color ?? VbeTheme.getSkeletonColor()}}>
  58. </View>
  59. )}
  60. </Animated.View>
  61. );
  62. }
  63. };
  64. export default VbeSkeleton;