ShiverBone.tsx 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import React, { memo } from 'react';
  2. import { View, StyleSheet } from 'react-native';
  3. import LinearGradient from 'react-native-linear-gradient';
  4. import Animated, {
  5. SharedValue,
  6. useAnimatedStyle,
  7. } from 'react-native-reanimated';
  8. import { useGetGradientTransform } from './hooks';
  9. import {
  10. useGetBoneStyles,
  11. useGetGradientSize,
  12. useGetGradientEndDirection,
  13. } from './hooks/index.js';
  14. import type {
  15. ISkeletonProps,
  16. ICustomViewStyle,
  17. IComponentSize,
  18. } from './constants';
  19. type ShiverBoneProps = Pick<
  20. ISkeletonProps,
  21. 'boneColor' | 'highlightColor' | 'animationType' | 'animationDirection'
  22. > & {
  23. componentSize: IComponentSize;
  24. boneLayout: ICustomViewStyle;
  25. animationValue: SharedValue<number>;
  26. index?: number | string;
  27. };
  28. /**
  29. * ShiverBone is a component that renders a rectangle with a gradient animation.
  30. * @componentSize is the size of the component.
  31. * @boneLayout is the layout of the bone.
  32. * @boneColor is the color of the bone.
  33. * @highlightColor is the color of the highlight.
  34. * @animationDirection is the direction of the animation.
  35. * @animationValue is the value of the animation.
  36. * @animationType is the type of the animation.
  37. * @index is the index of the bone.
  38. */
  39. const ShiverBone: React.FC<ShiverBoneProps> = ({
  40. componentSize,
  41. boneLayout,
  42. boneColor,
  43. highlightColor,
  44. animationDirection,
  45. animationValue,
  46. animationType,
  47. index,
  48. }) => {
  49. const transform = useGetGradientTransform({
  50. componentSize,
  51. boneLayout,
  52. animationDirection,
  53. animationValue,
  54. });
  55. const getBoneStyles = useGetBoneStyles(componentSize);
  56. const getGradientSize = useGetGradientSize(componentSize);
  57. const getGradientEndDirection = useGetGradientEndDirection(componentSize);
  58. const gradientSize = getGradientSize({ animationDirection, boneLayout });
  59. const animatedStyle = useAnimatedStyle(() => ({
  60. ...gradientSize,
  61. transform: [
  62. {
  63. translateX: transform.value.translateX ?? 0,
  64. },
  65. {
  66. translateY: transform.value.translateY ?? 0,
  67. },
  68. {
  69. rotate: transform.value.rotate ?? '0deg',
  70. },
  71. ],
  72. }));
  73. return (
  74. <View
  75. key={index}
  76. style={getBoneStyles({
  77. animationDirection,
  78. animationType,
  79. boneLayout,
  80. boneColor,
  81. })}
  82. >
  83. <Animated.View style={[styles.absoluteGradient, animatedStyle]}>
  84. <LinearGradient
  85. colors={[
  86. boneColor as string | number,
  87. highlightColor as string | number,
  88. boneColor as string | number,
  89. ]}
  90. start={{ x: 0, y: 0 }}
  91. end={getGradientEndDirection({
  92. animationType,
  93. animationDirection,
  94. boneLayout,
  95. })}
  96. style={styles.gradientChild}
  97. />
  98. </Animated.View>
  99. </View>
  100. );
  101. };
  102. export default memo(ShiverBone);
  103. const styles = StyleSheet.create({
  104. absoluteGradient: {
  105. height: '100%',
  106. position: 'absolute',
  107. width: '100%',
  108. },
  109. gradientChild: {
  110. flex: 1
  111. }
  112. });