react-native#Easing TypeScript Examples
The following examples show how to use
react-native#Easing.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: animation.ts From react-native-base-ui with MIT License | 6 votes |
animation: Animation = { timing100: 100, timing200: 200, timing300: 300, timing400: 400, timing500: 500, timing600: 600, timing700: 700, timing800: 800, timing900: 900, timing1000: 1000, easeInCurve: Easing.bezier(0.8, 0.2, 0.6, 1), easeOutCurve: Easing.bezier(0.2, 0.8, 0.4, 1), easeInOutCurve: Easing.bezier(0.4, 0, 0.2, 1), easeInQuinticCurve: Easing.bezier(0.755, 0.05, 0.855, 0.06), easeOutQuinticCurve: Easing.bezier(0.23, 1, 0.32, 1), easeInOutQuinticCurve: Easing.bezier(0.86, 0, 0.07, 1), linearCurve: Easing.bezier(0, 0, 1, 1), }
Example #2
Source File: TestAnimatedCard.tsx From react-native-anchor-point with MIT License | 6 votes |
componentDidMount() {
this._animation = Animated
.loop(
Animated.timing(this._rotateAnimatedValue, {
toValue: 1,
duration: 1500,
useNativeDriver: true,
easing: Easing.cubic
}),
{ iterations: 1000 },
)
.start();
}
Example #3
Source File: toolbar-context.tsx From react-native-cn-quill with MIT License | 6 votes |
hide = () => {
if (this.state.isAnimating) return;
const { theme } = this.props;
if (theme) {
this.setState({ isAnimating: true }, () => {
Animated.timing(this.animatedValue, {
toValue: theme.size + 10,
duration: 200,
easing: Easing.linear,
useNativeDriver: false,
}).start(() => {
this.setState({
name: '',
open: false,
options: [],
isAnimating: false,
});
});
});
}
};
Example #4
Source File: toolbar-context.tsx From react-native-cn-quill with MIT License | 6 votes |
show = (name: string, options: Array<ToggleData>) => {
if (this.state.isAnimating) return;
const { theme } = this.props;
if (theme) {
this.setState({ options, name, isAnimating: true }, () => {
Animated.timing(this.animatedValue, {
toValue: 2 * theme.size + 14,
duration: 200,
easing: Easing.sin,
useNativeDriver: false,
}).start(() => this.setState({ open: true, isAnimating: false }));
});
}
};
Example #5
Source File: TransitionSpecs.tsx From nlw2-proffy with MIT License | 6 votes |
ScaleFromCenterAndroidSpec: TransitionSpec = {
animation: 'timing',
config: {
duration: 400,
// This is super rough approximation of the path used for the curve by android
// See http://aosp.opersys.com/xref/android-10.0.0_r2/xref/frameworks/base/core/res/res/interpolator/fast_out_extra_slow_in.xml
easing: Easing.bezier(0.35, 0.45, 0, 1),
},
}
Example #6
Source File: TransitionSpecs.tsx From nlw2-proffy with MIT License | 6 votes |
RevealFromBottomAndroidSpec: TransitionSpec = {
animation: 'timing',
config: {
duration: 425,
// This is super rough approximation of the path used for the curve by android
// See http://aosp.opersys.com/xref/android-9.0.0_r47/xref/frameworks/base/core/res/res/interpolator/fast_out_extra_slow_in.xml
easing: Easing.bezier(0.35, 0.45, 0, 1),
},
}
Example #7
Source File: ProgressBar.tsx From react-native-jigsaw with MIT License | 6 votes |
animate() {
const { useNativeDriver = false, indeterminateAnimationDuration = 1000 } =
this.props;
this.state.animationValue.setValue(0);
Animated.timing(this.state.animationValue, {
toValue: 1,
duration: indeterminateAnimationDuration,
easing: Easing.linear,
isInteraction: false,
useNativeDriver,
}).start((endState) => {
if (endState.finished) {
this.animate();
}
});
}
Example #8
Source File: HudView.tsx From SQUID with MIT License | 6 votes |
_initializeRotationAnimation(isRotating) {
this.state.rotationAnim.setValue(0);
if (!isRotating && !this.state.isVisible) {
return;
}
Animated.timing(this.state.rotationAnim, {
toValue: 1,
duration: 800,
easing: Easing.linear
}).start(() => {
this._initializeRotationAnimation();
});
}
Example #9
Source File: RefreshButton.tsx From BitcoinWalletMobile with MIT License | 6 votes |
RefreshButton : React.FC<Props> = (props) => {
let rotation = new Animated.Value(0)
const animation = Animated.loop(Animated.timing(rotation, {
toValue: 1,
duration: 1000,
easing: Easing.linear,
useNativeDriver: true,
})).start()
const spin = rotation.interpolate({
inputRange: [0, 1],
outputRange: ['0deg', '360deg']
})
return (
<View>
<TouchableOpacity onPress={props.pressed} style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Animated.Image style={[styles.icon, {transform: props.refeshing ? [{rotate: spin}] : []}]} source={require('../assets/images/refresh.png')} />
</TouchableOpacity>
</View>
);
}
Example #10
Source File: AnimatedCircularProgress.tsx From react-native-jigsaw with MIT License | 5 votes |
AnimatedCircularProgress: React.FC<Props> = ({
duration = 500,
easing = Easing.out(Easing.ease),
fill,
prefill = 0,
useNativeDriver = false,
tintColorSecondary,
onAnimationComplete,
tintColor = "black",
...other
}) => {
const [fillAnimation] = React.useState<Animated.Value>(
new Animated.Value(prefill)
);
const animate = React.useCallback(
(
toVal: number = -1,
dur?: number,
ease?: EasingFunction
): Animated.CompositeAnimation => {
const toValue = toVal >= 0 ? toVal : fill;
const dura = dur || duration;
const eas = ease || easing;
const useNative = useNativeDriver;
const anim = Animated.timing(fillAnimation, {
useNativeDriver: useNative,
toValue,
easing: eas,
duration: dura,
});
anim.start(onAnimationComplete);
return anim;
},
[
duration,
easing,
fill,
useNativeDriver,
fillAnimation,
onAnimationComplete,
]
);
const animateColor = () => {
if (!tintColorSecondary) {
return tintColor;
}
const tintAnimation = fillAnimation.interpolate({
inputRange: [0, 100],
outputRange: [tintColor, tintColorSecondary],
});
return tintAnimation;
};
React.useEffect(() => {
animate();
}, [fill, animate]);
return (
<AnimatedProgress
{...other}
style={other.style as Animated.WithAnimatedValue<StyleProp<ViewStyle>>}
childrenContainerStyle={
other.childrenContainerStyle as Animated.WithAnimatedValue<
StyleProp<ViewStyle>
>
}
fill={fillAnimation}
tintColor={animateColor()}
/>
);
}
Example #11
Source File: ProgressIndicator.tsx From natds-rn with ISC License | 5 votes |
ProgressIndicatorComponent = ({
size = 'medium',
showLayer = false
}: ProgressIndicatorProps) => {
/**
* Duration specify how much the circle will take to make a 720deg loop around itself,
* decrease it will speed up the animation speed and increase will slow the animation speed
* The default speed is 1.4 second per loop
*/
const duration = 1400
/**
* This animation/Animated.timing, is responsible for looping the border around the view.
*/
const timer = useRef(new Animated.Value(0)).current
const rotation = Animated.timing(timer, {
duration,
easing: Easing.inOut(Easing.quad),
isInteraction: false,
toValue: 1,
useNativeDriver: Platform.OS !== 'web'
})
/**
* The rotate animation will take from 0deg to 720deg to make a full loop around itself
*/
const minCircularRange = '0deg'
const maxCircularRange = '720deg'
const layerStyle = {
transform: [
{
rotate: timer.interpolate({
inputRange: [0, 1],
outputRange: [minCircularRange, maxCircularRange]
})
}
]
}
/**
* Loop rotation animation continuously,
* each time it reaches the end, it resets and begins again from the start.
*/
const startRotation = useCallback((): void => {
timer.setValue(0)
Animated.loop(rotation).start()
}, [rotation, timer])
/**
* Reset the timer and loop the animation again on each update
*/
useEffect(() => {
startRotation()
}, [startRotation])
return (
<View size={size} showLayer={showLayer}>
<Layer as={Animated.View} size={size} style={layerStyle}>
<Container as={Animated.View} size={size}>
<Line as={Animated.View} size={size} />
</Container>
</Layer>
</View>
)
}
Example #12
Source File: index.tsx From krmanga with MIT License | 5 votes |
function LightDrawer({ chapterList, bookInfo, headerHeight, drawerX, goMangaView, hideDrawer }: IProps) {
const spinValue = useRef(new Animated.Value(0)).current;
const spin = spinValue.interpolate({
inputRange: [0, 1],
outputRange: ["0deg", "360deg"]
});
const [isSpin, setIsSpin] = useState<boolean>(true);
const [data, setData] = useState<IChapter[] | []>([]);
useEffect(() => {
setData(chapterList);
}, [chapterList]);
const onPress = () => {
if (typeof hideDrawer === "function") {
hideDrawer();
}
};
const renderItem = ({ item }: ListRenderItemInfo<IChapter>) => {
return (
<Item data={item} goMangaView={goMangaView} />
);
};
const reverse = () => {
if (isSpin) {
Animated.timing(
spinValue,
{
toValue: 0.5,
duration: 250,
easing: Easing.linear,
useNativeDriver: true
}
).start();
} else {
Animated.timing(
spinValue,
{
toValue: 1,
duration: 250,
easing: Easing.linear,
useNativeDriver: true
}
).start(() => spinValue.setValue(0));
}
setData([...data.reverse()]);
setIsSpin(!isSpin);
};
return (
<Animated.View style={[styles.wrapper, {
transform: [{ translateX: drawerX }]
}]}>
<View style={styles.container}>
<Touchable onPress={onPress} style={styles.transparentView} />
<View style={[styles.listContainer, {
paddingTop: headerHeight
}]}>
<Header bookInfo={bookInfo} spin={spin} reverse={reverse} />
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={(item, key) => `item-${key}-item-${item.id}`}
/>
</View>
</View>
</Animated.View>
);
}
Example #13
Source File: index.tsx From krmanga with MIT License | 5 votes |
function DarkDrawer({ chapterList, bookInfo, headerHeight, drawerX, goMangaView, hideDrawer }: IProps) {
const spinValue = useRef(new Animated.Value(0)).current;
const spin = spinValue.interpolate({
inputRange: [0, 1],
outputRange: ["0deg", "360deg"]
});
const [isSpin, setIsSpin] = useState<boolean>(true);
const [data, setData] = useState<IChapter[] | []>([]);
useEffect(() => {
setData(chapterList);
}, [chapterList]);
const onPress = () => {
if (typeof hideDrawer === "function") {
hideDrawer();
}
};
const renderItem = ({ item }: ListRenderItemInfo<IChapter>) => {
return (
<Item data={item} goMangaView={goMangaView} />
);
};
const reverse = () => {
if (isSpin) {
Animated.timing(
spinValue,
{
toValue: 0.5,
duration: 250,
easing: Easing.linear,
useNativeDriver: true
}
).start();
} else {
Animated.timing(
spinValue,
{
toValue: 1,
duration: 250,
easing: Easing.linear,
useNativeDriver: true
}
).start(() => spinValue.setValue(0));
}
setData([...data.reverse()]);
setIsSpin(!isSpin);
};
return (
<Animated.View style={[styles.wrapper, {
transform: [{ translateX: drawerX }]
}]}>
<View style={styles.container}>
<View style={[styles.listContainer, {
paddingTop: headerHeight
}]}>
<Header bookInfo={bookInfo} spin={spin} reverse={reverse} />
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={(item, key) => `item-${key}-item-${item.id}`}
/>
</View>
<Touchable onPress={onPress} style={styles.transparentView} />
</View>
</Animated.View>
);
}
Example #14
Source File: SegmentedControl.tsx From lexicon with MIT License | 5 votes |
export function SegmentedControl<T>(props: Props<T>) {
const styles = useStyles();
const { spacing } = useTheme();
const { values, selectedIndex, width, labelExtractor, onItemPress } = props;
const positionValue = useRef(new Animated.Value(0)).current;
const onSegmentSelected = (value: T, index: number) => {
onItemPress(value, index);
Animated.timing(positionValue, {
toValue: index,
duration: 100,
easing: Easing.ease,
useNativeDriver: false,
}).start(() => {});
};
// 20 is coming from the text line height (medium)
// SPACING.s (4) is coming from the segment padding
const IOS_SEGMENT_HEIGHT = 20 + spacing.s * 2;
// SPACING.xxl (24) is coming from the padding inside the Home Screen (Left and Right)
// SPACING.s (4) is coming from the initial (left) padding of the Segmented Control container
const IOS_SEGMENT_WIDTH =
(width - (spacing.xxl * 2 + spacing.s)) / values.length;
return (
<View style={styles.container}>
{ios && (
<Animated.View
style={[
{
transform: [
{
translateX: positionValue.interpolate({
inputRange: [0, values.length - 1],
// 4 is coming from initial padding of the container
outputRange: [4, (values.length - 1) * IOS_SEGMENT_WIDTH],
}),
},
],
},
styles.animatedSegment,
{
height: IOS_SEGMENT_HEIGHT,
width: IOS_SEGMENT_WIDTH,
},
]}
/>
)}
{values.map((value, index) => (
<TouchableOpacity
key={index}
style={[styles.item, selectedIndex === index && styles.itemChosen]}
onPress={() => onSegmentSelected(value, index)}
disabled={selectedIndex === index}
>
<Text
style={[styles.text, selectedIndex === index && styles.textChosen]}
>
{labelExtractor(value)}
</Text>
</TouchableOpacity>
))}
</View>
);
}
Example #15
Source File: index.tsx From jellyfin-audio-player with MIT License | 5 votes |
function NowPlaying() {
const { index, track } = useCurrentTrack();
const { buffered, duration, position } = useProgress();
const defaultStyles = useDefaultStyles();
const previousIndex = usePrevious(index);
const navigation = useNavigation<MusicNavigationProp>();
const bufferAnimation = useRef(new Animated.Value(0));
const progressAnimation = useRef(new Animated.Value(0));
const openNowPlayingModal = useCallback(() => {
navigation.navigate('Player');
}, [navigation]);
useEffect(() => {
const hasChangedTrack = previousIndex !== index || duration === 0;
Animated.timing(bufferAnimation.current, {
toValue: calculateProgressTranslation(buffered, duration, NOW_PLAYING_POPOVER_WIDTH),
duration: hasChangedTrack ? 0 : 500,
useNativeDriver: true,
easing: Easing.ease,
}).start();
Animated.timing(progressAnimation.current, {
toValue: calculateProgressTranslation(position, duration, NOW_PLAYING_POPOVER_WIDTH),
duration: hasChangedTrack ? 0 : 500,
useNativeDriver: true,
}).start();
}, [buffered, duration, position, index, previousIndex]);
if (!track) {
return null;
}
return (
<Container>
<ShadowOverlay pointerEvents='none'>
<Shadow distance={30} viewStyle={{ alignSelf: 'stretch', flexBasis: '100%' }} startColor="#00000017">
<View style={{ flex: 1, borderRadius: 8 }} />
</Shadow>
</ShadowOverlay>
<ColoredBlurView style={{ borderRadius: 8 }}>
<InnerContainer onPress={openNowPlayingModal} activeOpacity={0.5}>
<ShadowWrapper size="small">
<Cover source={{ uri: (track.artwork || '') as string }} style={defaultStyles.imageBackground} />
</ShadowWrapper>
<TrackNameContainer>
<Text numberOfLines={1}>{track.title}</Text>
<Text style={{ opacity: 0.5 }} numberOfLines={1}>
{track.artist}{track.album ? ` — ${track.album}` : ''}
</Text>
</TrackNameContainer>
<ActionButton>
<SelectActionButton />
</ActionButton>
<ProgressTrack
style={{ transform: [{ translateX: bufferAnimation.current }]}}
opacity={0.15}
stroke={4}
/>
<ProgressTrack
style={{ transform: [{ translateX: progressAnimation.current }]}}
stroke={4}
/>
</InnerContainer>
</ColoredBlurView>
</Container>
);
}
Example #16
Source File: AddToBagButton.tsx From RNChallenge_2 with MIT License | 5 votes |
AddToBagButton = ({addToCart}: Props) => {
const shakeAnim = useRef(new Animated.Value(0)).current;
const shakeAnimation = () => {
Animated.sequence([
Animated.timing(shakeAnim, {
toValue: 3,
duration: 100,
easing: Easing.cubic,
useNativeDriver: true,
}),
Animated.timing(shakeAnim, {
toValue: -3,
duration: 100,
easing: Easing.cubic,
useNativeDriver: true,
}),
Animated.timing(shakeAnim, {
toValue: 3,
duration: 100,
easing: Easing.cubic,
useNativeDriver: true,
}),
Animated.timing(shakeAnim, {
toValue: 0,
duration: 100,
easing: Easing.cubic,
useNativeDriver: true,
}),
]).start();
addToCart();
};
return (
<TouchableOpacity
onPress={shakeAnimation}
activeOpacity={0.7}
style={[styles.container]}>
<Animated.Image
resizeMethod={'resize'}
resizeMode={'contain'}
style={{
width: 25,
height: 25,
transform: [{translateY: shakeAnim}],
}}
source={require('../Assets/Icons/bag.png')}
/>
<Text style={[styles.Add]}>Add To Bag</Text>
</TouchableOpacity>
);
}
Example #17
Source File: index.tsx From expo-dark-mode-switch with MIT License | 5 votes |
MoonIcon = ({ isClicked, ...props }) => {
const value = createAnimatedValue(isClicked);
React.useEffect(() => {
Animated.timing(value.current, {
toValue: isClicked ? 1 : 0,
duration: transitionTime,
useNativeDriver: false,
easing: Easing.inOut(Easing.linear)
}).start();
}, [isClicked]);
return (
<Animated.View
style={[
styles.moonSvg,
{
opacity: value.current,
transform: [
{
translateY: value.current.interpolate({
inputRange: [0, 1],
outputRange: [30, 0],
}),
},
],
},
props.style,
]}
>
<SVG.Svg
pointerEvents="none"
{...props}
style={[styles.moonSvg, props.style]}
viewBox="0 0 30 32"
>
<SVG.Path
fill="white"
d="M22.592 21.504q3.36 0 6.56-1.792-1.344 4.64-5.184 7.616t-8.8 2.976q-6.016 0-10.304-4.288t-4.288-10.336q0-4.928 2.976-8.768t7.584-5.216q-1.792 3.2-1.792 6.56 0 5.504 3.904 9.376t9.344 3.872z"
/>
</SVG.Svg>
</Animated.View>
);
}
Example #18
Source File: ConcentricCircles.tsx From companion-kit with MIT License | 5 votes |
export function ConcentricCircle(props: ConcentricCircleProps) {
const { strokeBgColor, strokeColor, strokeWidth, radiusDecremented, radius, progress, animationStep } = props;
const diameter = radiusDecremented * 2;
const length = Math.round(diameter * Math.PI);
const offset = React.useMemo(() => {
if (!animationStep) {
return null;
}
const startProgress = progress - animationStep;
return new Animated.Value(getOffset(diameter, startProgress));
}, [animationStep, diameter, progress]);
React.useEffect(() => {
if (offset != null) {
Animated.timing(offset, {
toValue: getOffset(diameter, progress),
duration: 1500,
easing: Easing.inOut(Easing.ease),
}).start();
}
}, [progress]);
return (
<>
<Circle
cx={radius}
cy={radius}
r={radiusDecremented}
strokeWidth={strokeWidth}
stroke={strokeBgColor}
fill="none"
/>
<AnimatedContainer
fill="none"
cx={radius}
cy={radius}
r={radiusDecremented}
strokeWidth={strokeWidth}
stroke={strokeColor}
strokeDasharray={length}
strokeDashoffset={offset}
origin={`${radius}, ${radius}`}
rotation={-90}
/>
</>
);
}
Example #19
Source File: TransitionSpecs.tsx From nlw2-proffy with MIT License | 5 votes |
FadeOutToBottomAndroidSpec: TransitionSpec = {
animation: 'timing',
config: {
duration: 150,
easing: Easing.in(Easing.linear),
},
}
Example #20
Source File: TransitionSpecs.tsx From nlw2-proffy with MIT License | 5 votes |
FadeInFromBottomAndroidSpec: TransitionSpec = {
animation: 'timing',
config: {
duration: 350,
easing: Easing.out(Easing.poly(5)),
},
}
Example #21
Source File: FeedSideBar.tsx From react-native-tiktok-clone with MIT License | 5 votes |
FeedSideBar: React.FC<Props> = (props) => {
// Animate spinning song cover
const spinValue = useRef(new Animated.Value(0)).current;
const spin = spinValue.interpolate({
inputRange: [0, 1],
outputRange: ['0deg', '360deg'],
});
useEffect(() => {
Animated.loop(
Animated.timing(spinValue, {
toValue: 1,
duration: 11000,
easing: Easing.linear,
useNativeDriver: true,
}),
).start();
}, []);
let abbrLoveCount = abbreviateNum(props.love);
const onLovePress = useCallback(() => { props.onLoveReact(props.feedId) }, []);
return (
<View style={props.style}>
<Image
source={require('../../assets/icons/profile_img_frame.png')}
style={styles.profImageFrame}
/>
<Image source={{ uri: props.accountAvatar }} style={styles.profImage} />
<View style={styles.icon}>
<TouchableOpacity onPress={onLovePress}>
<Image
source={require('../../assets/icons/love.png')}
style={[styles.iconImg, props.isLoved && styles.loved]}
/>
</TouchableOpacity>
</View>
<Text style={styles.text}>{abbrLoveCount}</Text>
<View style={styles.icon}>
<TouchableOpacity>
<Image
source={require('../../assets/icons/comment.png')}
style={styles.iconImg}
/>
</TouchableOpacity>
</View>
<Text style={styles.text}>{props.comment}</Text>
<View style={styles.icon}>
<TouchableOpacity>
<Image
source={require('../../assets/icons/share.png')}
style={styles.iconImg}
/>
</TouchableOpacity>
</View>
<Text style={styles.text}>{props.share}</Text>
<Animated.Image
source={require('../../assets/icons/song_cover.png')}
style={[styles.songCover, { transform: [{ rotate: spin }] }]}
/>
</View>
);
}
Example #22
Source File: TextField.tsx From rn-credit-card with MIT License | 4 votes |
TextField = React.forwardRef<TextInput, Props>((props, ref) => {
const {
label,
errorText,
value,
endEnhancer,
style,
onBlur,
onFocus,
...restOfProps
} = props
const { inputColors = {}, fonts, overrides } = useContext(LibraryContext)
const {
errored: errorColor = '#B00020',
focused: focusedColor = '#080F9C',
regular: regularColor = '#B9C4CA',
} = inputColors
const [isFocused, setIsFocused] = useState(false)
const focusAnim = useRef(new Animated.Value(0)).current
useEffect(() => {
Animated.timing(focusAnim, {
toValue: isFocused || !!value ? 1 : 0,
duration: 150,
easing: Easing.bezier(0.4, 0, 0.2, 1),
useNativeDriver: true,
}).start()
}, [focusAnim, isFocused, value])
let color = isFocused ? focusedColor : regularColor
if (errorText) {
color = errorColor
}
return (
<View style={style}>
<TextInput
style={[
styles.input,
{
fontFamily: fonts.regular,
},
overrides.input,
{
borderColor: color,
},
]}
ref={ref}
{...restOfProps}
value={value}
onBlur={(event) => {
setIsFocused(false)
onBlur?.(event)
}}
onFocus={(event) => {
setIsFocused(true)
onFocus?.(event)
}}
/>
<TouchableWithoutFeedback
onPress={() => {
// @ts-ignore
ref?.current?.focus()
}}
>
<Animated.View
style={[
styles.labelContainer,
{
transform: [
{
scale: focusAnim.interpolate({
inputRange: [0, 1],
outputRange: [1, 0.75],
}),
},
{
translateY: focusAnim.interpolate({
inputRange: [0, 1],
outputRange: [24, -12],
}),
},
{
translateX: focusAnim.interpolate({
inputRange: [0, 1],
outputRange: [16, 0],
}),
},
],
},
overrides.labelContainer,
]}
>
<Text
style={[
styles.label,
overrides.inputLabel,
{
color,
},
]}
bold
>
{label}
{errorText ? '*' : ''}
</Text>
</Animated.View>
</TouchableWithoutFeedback>
{endEnhancer && (
<View style={styles.enhancerContainer}>{endEnhancer}</View>
)}
{!!errorText && (
<Text style={[styles.error, overrides.errorText]}>{errorText}</Text>
)}
</View>
)
})
Example #23
Source File: Ripple.tsx From mobile with Apache License 2.0 | 4 votes |
Ripple = ({
children,
disabled,
rippleColor = 'rgb(0, 0, 0)',
rippleCentered = false,
rippleOpacity = 0.3,
rippleExpandDuration = 500,
rippleFadeDuration = 200,
rippleContainerBorderRadius = 0,
rippleSize = 0,
...touchableWithoutFeedbackProps
}: RippleProps) => {
const [width, setWidth] = useState(0);
const [height, setHeight] = useState(0);
const uuid = useRef(0);
const [ripples, setRipples] = useState<AnimatedRipple[]>([]);
const [fadings, setFadings] = useState<number[]>([]);
const startFade = useCallback(
(ripple: AnimatedRipple, duration: number) => {
if (fadings.indexOf(ripple.id) >= 0) {
return;
}
setFadings([...fadings, ripple.id]);
Animated.timing(ripple.fadeAnimatedValue, {
toValue: 1,
easing: Easing.out(Easing.ease),
duration,
useNativeDriver: true,
}).start(() => {
setRipples(ripples.filter(item => item !== ripple));
});
},
[fadings, ripples],
);
const startExpand = useCallback(
(event: GestureResponderEvent) => {
if (!width || !height) {
return;
}
const timestamp = Date.now();
if (ripples.length > 0 && timestamp < ripples[ripples.length - 1].timestamp + DEBOUNCE) {
return;
}
const w2 = 0.5 * width;
const h2 = 0.5 * height;
const {locationX, locationY} = rippleCentered ? {locationX: w2, locationY: h2} : event.nativeEvent;
const offsetX = Math.abs(w2 - locationX);
const offsetY = Math.abs(h2 - locationY);
const radius = rippleSize > 0 ? 0.5 * rippleSize : Math.sqrt((w2 + offsetX) ** 2 + (h2 + offsetY) ** 2);
const id = uuid.current;
uuid.current += 1;
const ripple: AnimatedRipple = {
id,
locationX,
locationY,
radius,
timestamp,
expandAnimatedValue: new Animated.Value(0),
fadeAnimatedValue: new Animated.Value(0),
};
Animated.timing(ripple.expandAnimatedValue, {
toValue: 1,
easing: Easing.out(Easing.ease),
duration: rippleExpandDuration,
useNativeDriver: true,
}).start();
setRipples(ripples.concat(ripple));
},
[height, rippleCentered, rippleExpandDuration, rippleSize, ripples, width],
);
const onLayout = useCallback(
(event: LayoutChangeEvent) => {
const {
nativeEvent: {
layout: {height, width},
},
} = event;
setWidth(width);
setHeight(height);
touchableWithoutFeedbackProps.onLayout?.(event);
},
[touchableWithoutFeedbackProps.onLayout],
);
const onPressIn = useCallback(
(event: GestureResponderEvent) => {
startExpand(event);
touchableWithoutFeedbackProps.onPressIn?.(event);
},
[startExpand, touchableWithoutFeedbackProps.onPressIn],
);
const onPressOut = useCallback(
(event: GestureResponderEvent) => {
ripples.forEach(ripple => startFade(ripple, rippleFadeDuration + rippleExpandDuration / 2));
touchableWithoutFeedbackProps.onPressOut?.(event);
},
[rippleExpandDuration, rippleFadeDuration, ripples, startFade, touchableWithoutFeedbackProps.onPressOut],
);
const onPress = useCallback(
(event: GestureResponderEvent) => {
requestAnimationFrame(() => {
touchableWithoutFeedbackProps.onPress?.(event);
});
},
[touchableWithoutFeedbackProps.onPress],
);
const renderRipple = useCallback(
({locationX, locationY, radius, id, expandAnimatedValue, fadeAnimatedValue}: AnimatedRipple) => {
const rippleStyle = {
top: locationY - RADIUS,
[I18nManager.isRTL ? 'right' : 'left']: locationX - RADIUS,
backgroundColor: rippleColor,
transform: [
{
scale: expandAnimatedValue.interpolate({
inputRange: [0, 1],
outputRange: [0.5 / RADIUS, radius / RADIUS],
}),
},
],
opacity: fadeAnimatedValue.interpolate({
inputRange: [0, 1],
outputRange: [rippleOpacity, 0],
}),
};
return <Animated.View style={[styles.ripple, rippleStyle]} key={id} />;
},
[rippleColor, rippleOpacity],
);
const style = useMemo(
() => [
styles.container,
{
borderRadius: rippleContainerBorderRadius,
},
],
[rippleContainerBorderRadius],
);
return (
<TouchableWithoutFeedback
{...touchableWithoutFeedbackProps}
disabled={disabled}
onPressIn={onPressIn}
onPressOut={onPressOut}
onPress={onPress}
onLayout={onLayout}
>
<Animated.View pointerEvents="box-only">
<View style={style}>{ripples.map(renderRipple)}</View>
{children}
</Animated.View>
</TouchableWithoutFeedback>
);
}
Example #24
Source File: index.tsx From react-native-gifted-charts with MIT License | 4 votes |
BarChart = (props: PropTypes) => {
const scrollRef = useRef();
const [points, setPoints] = useState('');
const [selectedIndex, setSelectedIndex] = useState(-1);
const showLine = props.showLine || false;
const initialSpacing =
props.initialSpacing === 0 ? 0 : props.initialSpacing || 40;
const data = useMemo(() => props.data || [], [props.data]);
const lineData = props.lineData || data;
const defaultLineConfig = {
initialSpacing: initialSpacing,
curved: false,
isAnimated: false,
thickness: 1,
color: 'black',
hideDataPoints: false,
dataPointsShape: 'circular',
dataPointsWidth: 2,
dataPointsHeight: 2,
dataPointsColor: 'black',
dataPointsRadius: 3,
textColor: 'gray',
textFontSize: 10,
textShiftX: 0,
textShiftY: 0,
shiftY: 0,
delay: 0,
startIndex: 0,
endIndex: lineData.length - 1,
};
const lineConfig = props.lineConfig
? {
initialSpacing:
props.lineConfig.initialSpacing === 0
? 0
: props.lineConfig.initialSpacing ||
defaultLineConfig.initialSpacing,
curved: props.lineConfig.curved || defaultLineConfig.curved,
isAnimated: props.lineConfig.isAnimated || defaultLineConfig.isAnimated,
thickness: props.lineConfig.thickness || defaultLineConfig.thickness,
color: props.lineConfig.color || defaultLineConfig.color,
hideDataPoints:
props.lineConfig.hideDataPoints || defaultLineConfig.hideDataPoints,
dataPointsShape:
props.lineConfig.dataPointsShape || defaultLineConfig.dataPointsShape,
dataPointsHeight:
props.lineConfig.dataPointsHeight ||
defaultLineConfig.dataPointsHeight,
dataPointsWidth:
props.lineConfig.dataPointsWidth || defaultLineConfig.dataPointsWidth,
dataPointsColor:
props.lineConfig.dataPointsColor || defaultLineConfig.dataPointsColor,
dataPointsRadius:
props.lineConfig.dataPointsRadius ||
defaultLineConfig.dataPointsRadius,
textColor: props.lineConfig.textColor || defaultLineConfig.textColor,
textFontSize:
props.lineConfig.textFontSize || defaultLineConfig.textFontSize,
textShiftX: props.lineConfig.textShiftX || defaultLineConfig.textShiftX,
textShiftY: props.lineConfig.textShiftY || defaultLineConfig.textShiftY,
shiftY: props.lineConfig.shiftY || defaultLineConfig.shiftY,
delay: props.lineConfig.delay || defaultLineConfig.delay,
startIndex: props.lineConfig.startIndex || defaultLineConfig.startIndex,
endIndex:
props.lineConfig.endIndex === 0
? 0
: props.lineConfig.endIndex || defaultLineConfig.endIndex,
}
: defaultLineConfig;
const containerHeight = props.height || 200;
const noOfSections = props.noOfSections || 10;
const horizSections = [{value: '0'}];
const horizSectionsBelow = [];
const stepHeight = props.stepHeight || containerHeight / noOfSections;
const spacing = props.spacing === 0 ? 0 : props.spacing || 20;
const labelWidth = props.labelWidth || 0;
const scrollToEnd = props.scrollToEnd || false;
const scrollAnimation = props.scrollAnimation === false ? false : true;
const labelsExtraHeight = props.labelsExtraHeight || 0;
let totalWidth = spacing;
let maxItem = 0,
minItem = 0;
if (props.stackData) {
props.stackData.forEach(stackItem => {
// console.log('stackItem', stackItem);
let stackSum = stackItem.stacks.reduce(
(acc, stack) => acc + stack.value,
0,
);
// console.log('stackSum--->', stackSum);
if (stackSum > maxItem) {
maxItem = stackSum;
}
if (stackSum < minItem) {
minItem = stackSum;
}
totalWidth +=
(stackItem.stacks[0].barWidth || props.barWidth || 30) + spacing;
// console.log('totalWidth for stack===', totalWidth);
});
} else {
data.forEach((item: itemType) => {
if (item.value > maxItem) {
maxItem = item.value;
}
if (item.value < minItem) {
minItem = item.value;
}
totalWidth +=
(item.barWidth || props.barWidth || 30) +
(item.spacing === 0 ? 0 : item.spacing || spacing);
// console.log('totalWidth for bar===', totalWidth);
});
}
if (props.showFractionalValues || props.roundToDigits) {
maxItem *= 10 * (props.roundToDigits || 1);
maxItem = maxItem + (10 - (maxItem % 10));
maxItem /= 10 * (props.roundToDigits || 1);
maxItem = parseFloat(maxItem.toFixed(props.roundToDigits || 1));
if (minItem !== 0) {
minItem *= 10 * (props.roundToDigits || 1);
minItem = minItem - (10 + (minItem % 10));
minItem /= 10 * (props.roundToDigits || 1);
minItem = parseFloat(minItem.toFixed(props.roundToDigits || 1));
}
} else {
maxItem = maxItem + (10 - (maxItem % 10));
if (minItem !== 0) {
minItem = minItem - (10 + (minItem % 10));
}
}
const maxValue = props.maxValue || maxItem;
const minValue = props.minValue || minItem;
const stepValue = props.stepValue || maxValue / noOfSections;
const noOfSectionsBelowXAxis =
props.noOfSectionsBelowXAxis || -minValue / stepValue;
const disableScroll = props.disableScroll || false;
const showScrollIndicator = props.showScrollIndicator || false;
// const oldData = props.oldData || [];
const side = props.side || '';
const rotateLabel = props.rotateLabel || false;
const isAnimated = props.isAnimated || false;
const animationDuration = props.animationDuration || 800;
// const animationEasing = props.animationEasing || Easing.ease;
const opacity = props.opacity || 1;
const isThreeD = props.isThreeD || false;
const showVerticalLines = props.showVerticalLines || false;
const rulesThickness =
props.rulesThickness === 0 ? 0 : props.rulesThickness || 1;
const rulesColor = props.rulesColor || 'lightgray';
const verticalLinesThickness =
props.verticalLinesThickness === 0 ? 0 : props.verticalLinesThickness || 1;
const verticalLinesHeight = props.verticalLinesHeight;
const verticalLinesColor = props.verticalLinesColor || 'lightgray';
const verticalLinesZIndex = props.verticalLinesZIndex || -1;
let verticalLinesAr = [];
props.noOfVerticalLines
? (verticalLinesAr = [...Array(props.noOfVerticalLines).keys()])
: (verticalLinesAr = [
...Array(props.stackData ? props.stackData.length : data.length).keys(),
]);
const verticalLinesSpacing = props.verticalLinesSpacing || 0;
const showYAxisIndices = props.showYAxisIndices || false;
const showXAxisIndices = props.showXAxisIndices || false;
const yAxisIndicesHeight = props.yAxisIndicesHeight || 2;
const xAxisIndicesHeight = props.xAxisIndicesHeight || 2;
const yAxisIndicesWidth = props.yAxisIndicesWidth || 4;
const xAxisIndicesWidth = props.xAxisIndicesWidth || 4;
const xAxisIndicesColor = props.xAxisIndicesColor || 'black';
const yAxisIndicesColor = props.yAxisIndicesColor || 'black';
const yAxisLabelPrefix = props.yAxisLabelPrefix || '';
const yAxisLabelSuffix = props.yAxisLabelSuffix || '';
const yAxisSide = props.yAxisSide || 'left';
const xAxisThickness =
props.xAxisThickness === 0
? props.xAxisThickness
: props.xAxisThickness || 1;
const xAxisColor = props.xAxisColor || 'black';
const hideRules = props.hideRules || false;
const yAxisThickness =
props.yAxisThickness === 0
? props.yAxisThickness
: props.yAxisThickness || 1;
const yAxisColor = props.yAxisColor || 'black';
const yAxisTextStyle = props.yAxisTextStyle;
const yAxisTextNumberOfLines = props.yAxisTextNumberOfLines || 1;
const xAxisTextNumberOfLines = props.xAxisTextNumberOfLines || 1;
const yAxisLabelContainerStyle = props.yAxisLabelContainerStyle;
const horizontalRulesStyle = props.horizontalRulesStyle;
const showFractionalValues = props.showFractionalValues || false;
const yAxisLabelWidth = props.yAxisLabelWidth || 35;
const hideYAxisText = props.hideYAxisText || false;
const backgroundColor = props.backgroundColor || 'transparent';
const horizontal = props.horizontal || false;
const yAxisAtTop = props.yAxisAtTop || false;
const intactTopLabel = props.intactTopLabel || false;
const hideOrigin = props.hideOrigin || false;
const rulesType = props.rulesType || 'line';
const xAxisType = props.xAxisType || 'solid';
const dashWidth = props.dashWidth === 0 ? 0 : props.dashWidth || 4;
const dashGap = props.dashGap === 0 ? 0 : props.dashGap || 8;
const heightValue = useMemo(() => new Animated.Value(0), []);
const opacValue = useMemo(() => new Animated.Value(0), []);
const widthValue = useMemo(() => new Animated.Value(0), []);
const autoShiftLabels = props.autoShiftLabels || false;
const labelsAppear = useCallback(() => {
opacValue.setValue(0);
Animated.timing(opacValue, {
toValue: 1,
duration: 500,
easing: Easing.ease,
useNativeDriver: false,
}).start();
}, [opacValue]);
// const moveBar = useCallback(() => {
// heightValue.setValue(0);
// Animated.timing(heightValue, {
// toValue: 1,
// duration: animationDuration,
// easing: animationEasing,
// useNativeDriver: false,
// }).start();
// }, [animationDuration, animationEasing, heightValue]);
const decreaseWidth = useCallback(() => {
widthValue.setValue(0);
Animated.timing(widthValue, {
toValue: 1,
duration: animationDuration,
easing: Easing.linear,
useNativeDriver: false,
}).start();
}, [animationDuration, widthValue]);
// console.log('olddata', oldData);
useEffect(() => {
if (showLine) {
let pp = '';
if (!lineConfig.curved) {
for (let i = 0; i < lineData.length; i++) {
if (i < lineConfig.startIndex || i > lineConfig.endIndex) continue;
const currentBarWidth =
(data && data[i] && data[i].barWidth) || props.barWidth || 30;
pp +=
'L' +
(yAxisLabelWidth +
lineConfig.initialSpacing +
6 -
(initialSpacing - currentBarWidth / 2) -
lineConfig.dataPointsWidth / 2 +
(currentBarWidth + spacing) * i) +
' ' +
(containerHeight -
lineConfig.shiftY -
(lineData[i].value * containerHeight) / maxValue) +
' ';
}
setPoints(pp.replace('L', 'M'));
} else {
let p1Array = [];
for (let i = 0; i < lineData.length; i++) {
if (i < lineConfig.startIndex || i > lineConfig.endIndex) continue;
const currentBarWidth =
(data && data[i] && data[i].barWidth) || props.barWidth || 30;
p1Array.push([
yAxisLabelWidth +
lineConfig.initialSpacing +
6 -
(initialSpacing - currentBarWidth / 2) -
lineConfig.dataPointsWidth / 2 +
(currentBarWidth + spacing) * i,
containerHeight -
lineConfig.shiftY -
(lineData[i].value * containerHeight) / maxValue,
]);
let xx = svgPath(p1Array, bezierCommand);
setPoints(xx);
}
}
if (lineConfig.isAnimated) {
setTimeout(() => decreaseWidth(), lineConfig.delay || 0);
}
}
// moveBar();
setTimeout(() => labelsAppear(), animationDuration);
}, [
animationDuration,
containerHeight,
data,
lineData,
decreaseWidth,
initialSpacing,
labelsAppear,
lineConfig.initialSpacing,
lineConfig.curved,
lineConfig.dataPointsWidth,
lineConfig.shiftY,
lineConfig.isAnimated,
lineConfig.delay,
lineConfig.startIndex,
lineConfig.endIndex,
maxValue,
// moveBar,
props.barWidth,
showLine,
spacing,
yAxisLabelWidth,
]);
const defaultReferenceConfig = {
thickness: rulesThickness,
width: horizontal
? props.width || totalWidth
: (props.width || totalWidth) + 11,
color: 'black',
type: rulesType,
dashWidth: dashWidth,
dashGap: dashGap,
labelText: '',
labelTextStyle: null,
};
const showReferenceLine1 = props.showReferenceLine1 || false;
const referenceLine1Position =
props.referenceLine1Position === 0
? 0
: props.referenceLine1Position || containerHeight / 2;
const referenceLine1Config = props.referenceLine1Config
? {
thickness: props.referenceLine1Config.thickness || rulesThickness,
width: horizontal
? props.referenceLine1Config.width || props.width || totalWidth
: (props.referenceLine1Config.width || props.width || totalWidth) +
11,
color: props.referenceLine1Config.color || 'black',
type: props.referenceLine1Config.type || rulesType,
dashWidth: props.referenceLine1Config.dashWidth || dashWidth,
dashGap: props.referenceLine1Config.dashGap || dashGap,
labelText:
props.referenceLine1Config.labelText ||
defaultReferenceConfig.labelText,
labelTextStyle:
props.referenceLine1Config.labelTextStyle ||
defaultReferenceConfig.labelTextStyle,
}
: defaultReferenceConfig;
const showReferenceLine2 = props.showReferenceLine2 || false;
const referenceLine2Position =
props.referenceLine2Position === 0
? 0
: props.referenceLine2Position || (3 * containerHeight) / 2;
const referenceLine2Config = props.referenceLine2Config
? {
thickness: props.referenceLine2Config.thickness || rulesThickness,
width: horizontal
? props.referenceLine2Config.width || props.width || totalWidth
: (props.referenceLine2Config.width || props.width || totalWidth) +
11,
color: props.referenceLine2Config.color || 'black',
type: props.referenceLine2Config.type || rulesType,
dashWidth: props.referenceLine2Config.dashWidth || dashWidth,
dashGap: props.referenceLine2Config.dashGap || dashGap,
labelText:
props.referenceLine2Config.labelText ||
defaultReferenceConfig.labelText,
labelTextStyle:
props.referenceLine2Config.labelTextStyle ||
defaultReferenceConfig.labelTextStyle,
}
: defaultReferenceConfig;
const showReferenceLine3 = props.showReferenceLine3 || false;
const referenceLine3Position =
props.referenceLine3Position === 0
? 0
: props.referenceLine3Position || containerHeight / 3;
const referenceLine3Config = props.referenceLine3Config
? {
thickness: props.referenceLine3Config.thickness || rulesThickness,
width: horizontal
? props.referenceLine3Config.width || props.width || totalWidth
: (props.referenceLine3Config.width || props.width || totalWidth) +
11,
color: props.referenceLine3Config.color || 'black',
type: props.referenceLine3Config.type || rulesType,
dashWidth: props.referenceLine3Config.dashWidth || dashWidth,
dashGap: props.referenceLine3Config.dashGap || dashGap,
labelText:
props.referenceLine3Config.labelText ||
defaultReferenceConfig.labelText,
labelTextStyle:
props.referenceLine3Config.labelTextStyle ||
defaultReferenceConfig.labelTextStyle,
}
: defaultReferenceConfig;
horizSections.pop();
for (let i = 0; i <= noOfSections; i++) {
let value = maxValue - stepValue * i;
if (props.showFractionalValues || props.roundToDigits) {
value = parseFloat(value.toFixed(props.roundToDigits || 1));
}
horizSections.push({
value: props.yAxisLabelTexts
? props.yAxisLabelTexts[noOfSections - i] ?? value.toString()
: value.toString(),
});
}
if (noOfSectionsBelowXAxis) {
for (let i = 1; i <= noOfSectionsBelowXAxis; i++) {
let value = stepValue * -i;
if (props.showFractionalValues || props.roundToDigits) {
value = parseFloat(value.toFixed(props.roundToDigits || 1));
}
horizSectionsBelow.push({
value: props.yAxisLabelTexts
? props.yAxisLabelTexts[noOfSectionsBelowXAxis - i] ??
value.toString()
: value.toString(),
});
}
}
const animatedHeight = heightValue.interpolate({
inputRange: [0, 1],
outputRange: ['0%', '100%'],
});
const appearingOpacity = opacValue.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
});
const animatedWidth = widthValue.interpolate({
inputRange: [0, 1],
outputRange: [0, totalWidth],
});
const getLabel = (val, index) => {
let label = '';
if (
showFractionalValues ||
(props.yAxisLabelTexts && props.yAxisLabelTexts[index] !== undefined)
) {
if (val) {
label = val;
} else {
label = '0';
}
} else {
if (val) {
label = val.toString().split('.')[0];
} else {
label = '0';
}
}
return yAxisLabelPrefix + label + yAxisLabelSuffix;
};
const renderHorizSections = () => {
return (
<>
{horizSections.map((sectionItems, index) => {
return (
<View
key={index}
style={[
styles.horizBar,
{
width: horizontal
? props.width || Math.min(300, totalWidth)
: props.width || totalWidth + 11,
},
yAxisSide === 'right' && {transform: [{rotateY: '180deg'}]},
horizontalRulesStyle,
]}>
<View
style={[
styles.leftLabel,
{
borderRightWidth: yAxisThickness,
borderColor: yAxisColor,
},
horizontal &&
!yAxisAtTop && {
transform: [
{
translateX:
(props.width || Math.min(300, totalWidth)) +
yAxisThickness,
},
],
},
{
height:
index === noOfSections ? stepHeight / 2 : stepHeight,
width: yAxisLabelWidth,
},
yAxisLabelContainerStyle,
]}
/>
<View
style={[
index === noOfSections
? styles.lastLeftPart
: styles.leftPart,
{backgroundColor: backgroundColor},
]}>
{index === noOfSections ? (
<Rule
config={{
thickness: xAxisThickness,
color: xAxisColor,
width: horizontal
? props.width || Math.min(300, totalWidth)
: (props.width || totalWidth) + 11,
dashWidth: dashWidth,
dashGap: dashGap,
type: xAxisType,
}}
/>
) : hideRules ? null : (
<Rule
config={{
thickness: rulesThickness,
color: rulesColor,
width: horizontal
? props.width || Math.min(300, totalWidth)
: (props.width || totalWidth) + 11,
dashWidth: dashWidth,
dashGap: dashGap,
type: rulesType,
}}
/>
)}
</View>
</View>
);
})}
{
/***********************************************************************************************/
/************************** Render the y axis labels separately **********************/
/***********************************************************************************************/
props.hideAxesAndRules !== true &&
!hideYAxisText &&
horizSections.map((sectionItems, index) => {
let label = getLabel(sectionItems.value, index);
if (hideOrigin && index === horizSections.length - 1) {
label = '';
}
return (
<View
key={index}
style={[
styles.horizBar,
styles.leftLabel,
{
position: 'absolute',
zIndex: 1,
top: stepHeight * index,
width: yAxisLabelWidth,
height:
index === noOfSections ? stepHeight / 2 : stepHeight,
},
yAxisSide === 'right' && {
transform: [
{
translateX:
(props.width ? props.width : totalWidth) - 30,
},
{rotateY: '180deg'},
],
},
horizontal &&
!yAxisAtTop && {
transform: [
{
translateX:
(props.width || Math.min(300, totalWidth)) +
yAxisThickness +
yAxisLabelWidth,
},
],
},
yAxisLabelContainerStyle,
]}>
<Text
numberOfLines={yAxisTextNumberOfLines}
ellipsizeMode={'clip'}
style={[
yAxisTextStyle,
yAxisSide === 'right' && {
transform: [{rotateY: '180deg'}],
},
index === noOfSections && {
marginBottom: stepHeight / -2,
},
]}>
{label}
</Text>
</View>
);
})
/***********************************************************************************************/
/***********************************************************************************************/
}
{horizSectionsBelow.map((sectionItems, index) => {
return (
<View
key={index}
style={[
styles.horizBar,
{
width: horizontal
? props.width || totalWidth
: props.width || totalWidth + 11,
},
yAxisSide === 'right' && {transform: [{rotateY: '180deg'}]},
index === 0 && {marginTop: stepHeight / 2},
]}>
<View
style={[
styles.leftLabel,
{
borderRightWidth: yAxisThickness,
borderColor: yAxisColor,
},
horizontal &&
!yAxisAtTop && {
transform: [{translateX: totalWidth + yAxisThickness}],
},
{
height: index === 0 ? stepHeight * 1.5 : stepHeight,
width: yAxisLabelWidth,
},
index === 0 && {marginTop: -stepHeight / 2},
]}
/>
<View
style={[styles.leftPart, {backgroundColor: backgroundColor}]}>
{hideRules ? null : (
<Rule
config={{
thickness: rulesThickness,
color: rulesColor,
width: horizontal
? props.width || totalWidth
: (props.width || totalWidth) + 11,
dashWidth: dashWidth,
dashGap: dashGap,
type: rulesType,
}}
/>
)}
</View>
</View>
);
})}
{
/***********************************************************************************************/
/************************* Render the y axis labels below origin *********************/
/***********************************************************************************************/
props.hideAxesAndRules !== true &&
!hideYAxisText &&
horizSectionsBelow.map((sectionItems, index) => {
let label = getLabel(
horizSectionsBelow[horizSectionsBelow.length - 1 - index].value,
index,
);
return (
<View
key={index}
style={[
styles.horizBar,
styles.leftLabel,
{
position: 'absolute',
zIndex: 1,
bottom: stepHeight * (index - 1),
width: yAxisLabelWidth,
height:
index === noOfSections ? stepHeight / 2 : stepHeight,
},
yAxisSide === 'right' && {
transform: [
{
translateX:
(props.width ? props.width : totalWidth) - 30,
},
{rotateY: '180deg'},
],
},
yAxisLabelContainerStyle,
]}>
<Text
numberOfLines={yAxisTextNumberOfLines}
ellipsizeMode={'clip'}
style={[
yAxisTextStyle,
yAxisSide === 'right' && {
transform: [{rotateY: '180deg'}],
},
index === noOfSections && {
marginBottom: stepHeight / -2,
},
]}>
{label}
</Text>
</View>
);
})
/***********************************************************************************************/
/***********************************************************************************************/
}
{
/***********************************************************************************************/
/************************* Render the reference lines separately *********************/
/***********************************************************************************************/
props.hideAxesAndRules !== true &&
!hideYAxisText &&
horizSections.map((sectionItems, index) => {
let label = getLabel(sectionItems.value, index);
if (hideOrigin && index === horizSections.length - 1) {
label = '';
}
return (
<View
key={index}
style={[
styles.horizBar,
styles.leftLabel,
{
position: 'absolute',
zIndex: 1,
top: stepHeight * index,
width: yAxisLabelWidth,
height:
index === noOfSections ? stepHeight / 2 : stepHeight,
},
yAxisSide === 'right' && {
transform: [
{
translateX:
(props.width ? props.width : totalWidth) - 30,
},
{rotateY: '180deg'},
],
},
]}>
{index === noOfSections && showReferenceLine1 ? (
<View
style={{
position: 'absolute',
bottom:
(referenceLine1Position * containerHeight) / maxValue,
left:
yAxisSide === 'right'
? yAxisLabelWidth + yAxisThickness
: yAxisLabelWidth + yAxisThickness - 5,
}}>
<Rule config={referenceLine1Config} />
{referenceLine1Config.labelText ? (
<Text
style={[
{position: 'absolute'},
yAxisSide === 'right' && {
transform: [{rotateY: '180deg'}],
},
referenceLine1Config.labelTextStyle,
]}>
{referenceLine1Config.labelText}
</Text>
) : null}
</View>
) : null}
{index === noOfSections && showReferenceLine2 ? (
<View
style={{
position: 'absolute',
bottom:
(referenceLine2Position * containerHeight) / maxValue,
left:
yAxisSide === 'right'
? yAxisLabelWidth + yAxisThickness
: yAxisLabelWidth + yAxisThickness - 5,
}}>
<Rule config={referenceLine2Config} />
{referenceLine2Config.labelText ? (
<Text
style={[
{position: 'absolute'},
yAxisSide === 'right' && {
transform: [{rotateY: '180deg'}],
},
referenceLine2Config.labelTextStyle,
]}>
{referenceLine2Config.labelText}
</Text>
) : null}
</View>
) : null}
{index === noOfSections && showReferenceLine3 ? (
<View
style={{
position: 'absolute',
bottom:
(referenceLine3Position * containerHeight) / maxValue,
left:
yAxisSide === 'right'
? yAxisLabelWidth + yAxisThickness
: yAxisLabelWidth + yAxisThickness - 5,
}}>
<Rule config={referenceLine3Config} />
{referenceLine3Config.labelText ? (
<Text
style={[
{position: 'absolute'},
yAxisSide === 'right' && {
transform: [{rotateY: '180deg'}],
},
referenceLine3Config.labelTextStyle,
]}>
{referenceLine3Config.labelText}
</Text>
) : null}
</View>
) : null}
</View>
);
})
/***********************************************************************************************/
/***********************************************************************************************/
}
</>
);
};
const renderSpecificVerticalLines = (dataForRender: any) => {
return dataForRender.map((item: any, index: number) => {
if (item.showVerticalLine) {
const currentBarWidth = item.barWidth || props.barWidth || 30;
return (
<Rect
x={
yAxisLabelWidth +
6 -
(item.verticalLineThickness || 1) / 2 -
1 -
(initialSpacing - currentBarWidth / 2) +
(currentBarWidth + spacing) * index
}
y={
containerHeight -
lineConfig.shiftY -
(item.value * containerHeight) / maxValue +
9
}
width={item.verticalLineThickness || 1}
height={
(item.value * containerHeight) / maxValue + lineConfig.shiftY
}
fill={item.verticalLineColor || 'lightgray'}
/>
);
}
return null;
});
};
const renderDataPoints = () => {
return lineData.map((item: any, index: number) => {
if (index < lineConfig.startIndex || index > lineConfig.endIndex) {
return null;
}
// console.log('comes in');
const currentBarWidth = item.barWidth || props.barWidth || 30;
if (lineConfig.dataPointsShape === 'rectangular') {
return (
<Fragment key={index}>
<Rect
x={
yAxisLabelWidth +
lineConfig.initialSpacing +
6 -
(initialSpacing - currentBarWidth / 2) -
lineConfig.dataPointsWidth +
(currentBarWidth + spacing) * index
}
y={
containerHeight -
lineConfig.shiftY -
lineConfig.dataPointsHeight / 2 -
(item.value * containerHeight) / maxValue
}
width={lineConfig.dataPointsWidth}
height={lineConfig.dataPointsHeight}
fill={lineConfig.dataPointsColor}
/>
{item.dataPointText && (
<CanvasText
fill={item.textColor || lineConfig.textColor}
fontSize={item.textFontSize || lineConfig.textFontSize}
x={
yAxisLabelWidth +
lineConfig.initialSpacing +
6 -
(initialSpacing - currentBarWidth / 2) -
lineConfig.dataPointsWidth +
(currentBarWidth + spacing) * index +
(item.textShiftX || lineConfig.textShiftX || 0)
}
y={
containerHeight -
lineConfig.shiftY -
lineConfig.dataPointsHeight / 2 -
(item.value * containerHeight) / maxValue +
(item.textShiftY || lineConfig.textShiftY || 0)
}>
{item.dataPointText}
</CanvasText>
)}
</Fragment>
);
}
return (
<Fragment key={index}>
<Circle
cx={
yAxisLabelWidth +
lineConfig.initialSpacing +
6 -
(initialSpacing - currentBarWidth / 2) -
lineConfig.dataPointsWidth / 2 +
(currentBarWidth + spacing) * index
}
cy={
containerHeight -
lineConfig.shiftY -
(item.value * containerHeight) / maxValue
}
r={lineConfig.dataPointsRadius}
fill={lineConfig.dataPointsColor}
/>
{item.dataPointText && (
<CanvasText
fill={item.textColor || lineConfig.textColor}
fontSize={item.textFontSize || lineConfig.textFontSize}
x={
yAxisLabelWidth +
lineConfig.initialSpacing +
6 -
(initialSpacing - currentBarWidth / 2) -
lineConfig.dataPointsWidth +
(currentBarWidth + spacing) * index +
(item.textShiftX || lineConfig.textShiftX || 0)
}
y={
containerHeight -
lineConfig.shiftY -
lineConfig.dataPointsHeight / 2 -
(item.value * containerHeight) / maxValue +
(item.textShiftY || lineConfig.textShiftY || 0)
}>
{item.dataPointText}
</CanvasText>
)}
</Fragment>
);
});
};
const renderSpecificDataPoints = dataForRender => {
return dataForRender.map((item: any, index: number) => {
const currentBarWidth = item.barWidth || props.barWidth || 30;
if (item.showDataPoint) {
if (item.dataPointShape === 'rectangular') {
return (
<Fragment key={index}>
<Rect
x={
initialSpacing -
(item.dataPointWidth || 2) / 2 -
1 +
(currentBarWidth + spacing) * index
}
y={
containerHeight -
lineConfig.shiftY -
(item.dataPointHeight || 2) / 2 +
10 -
(item.value * containerHeight) / maxValue
}
width={item.dataPointWidth || 2}
height={item.dataPointHeight || 2}
fill={item.dataPointColor || 'black'}
/>
{item.dataPointText && (
<CanvasText
fill={item.textColor || 'black'}
fontSize={item.textFontSize || 10}
x={
initialSpacing -
(item.dataPointWidth || 2) +
spacing * index +
(item.textShiftX || lineConfig.textShiftX || 0)
}
y={
containerHeight -
lineConfig.shiftY -
(item.dataPointHeight || 2) / 2 +
10 -
(item.value * containerHeight) / maxValue +
(item.textShiftY || lineConfig.textShiftY || 0)
}>
{item.dataPointText}
</CanvasText>
)}
</Fragment>
);
} else {
return (
<Fragment key={index}>
<Circle
cx={
initialSpacing -
(item.dataPointWidth || 2) / 2 +
spacing * index
}
cy={
containerHeight -
lineConfig.shiftY +
10 -
(item.value * containerHeight) / maxValue
}
r={item.dataPointRadius || 3}
fill={item.dataPointColor || 'black'}
/>
{item.dataPointText && (
<CanvasText
fill={item.textColor || 'black'}
fontSize={item.textFontSize || 10}
x={
initialSpacing -
(item.dataPointWidth || 2) +
spacing * index +
(item.textShiftX || lineConfig.textShiftX || 0)
}
y={
containerHeight -
lineConfig.shiftY -
(item.dataPointHeight || 2) / 2 +
10 -
(item.value * containerHeight) / maxValue +
(item.textShiftY || lineConfig.textShiftY || 0)
}>
{item.dataPointText}
</CanvasText>
)}
</Fragment>
);
}
}
return null;
});
};
const renderAnimatedLine = () => {
// console.log('animatedWidth is-------->', animatedWidth);
return (
<Animated.View
style={{
position: 'absolute',
height: containerHeight + 10,
bottom: 60, //stepHeight * -0.5 + xAxisThickness,
width: animatedWidth,
zIndex: -1,
// backgroundColor: 'wheat',
}}>
<Svg>
<Path
d={points}
fill="none"
stroke={lineConfig.color}
strokeWidth={lineConfig.thickness}
/>
{renderSpecificVerticalLines(data)}
{!lineConfig.hideDataPoints
? renderDataPoints()
: renderSpecificDataPoints(data)}
</Svg>
</Animated.View>
);
};
const renderLine = () => {
return (
<View
style={{
position: 'absolute',
height: containerHeight + 10,
bottom: 60, //stepHeight * -0.5 + xAxisThickness,
width: totalWidth,
zIndex: -1,
// backgroundColor: 'rgba(200,150,150,0.1)'
}}>
<Svg>
<Path
d={points}
fill="none"
stroke={lineConfig.color}
strokeWidth={lineConfig.thickness}
/>
{renderSpecificVerticalLines(data)}
{!lineConfig.hideDataPoints
? renderDataPoints()
: renderSpecificDataPoints(data)}
</Svg>
</View>
);
};
return (
<View
style={[
styles.container,
{
height:
containerHeight +
horizSectionsBelow.length * stepHeight +
labelsExtraHeight,
},
yAxisSide === 'right' && {marginLeft: yAxisLabelWidth + yAxisThickness},
props.width && !horizontal && {width: props.width},
horizontal && {transform: [{rotate: '90deg'}, {translateY: 15}]},
]}>
{props.hideAxesAndRules !== true && renderHorizSections()}
<ScrollView
ref={scrollRef}
onTouchStart={evt => {
if (props.renderTooltip) {
setSelectedIndex(-1);
}
}}
onContentSizeChange={() => {
if (scrollRef.current && scrollToEnd) {
scrollRef.current.scrollToEnd({animated: scrollAnimation});
}
}}
style={[
{
marginLeft:
yAxisSide === 'right' ? -yAxisLabelWidth + 10 : yAxisLabelWidth,
position: 'absolute',
bottom: stepHeight * -0.5 - 60 + xAxisThickness,
},
props.width && {width: props.width - 11},
horizontal && {width: props.width || Math.min(300, totalWidth)},
]}
scrollEnabled={!disableScroll}
contentContainerStyle={[
{
// backgroundColor: 'yellow',
height:
containerHeight +
130 +
horizSectionsBelow.length * stepHeight +
labelsExtraHeight,
paddingLeft: initialSpacing,
paddingBottom:
horizSectionsBelow.length * stepHeight + labelsExtraHeight,
alignItems: 'flex-end',
},
!props.width && {width: totalWidth},
]}
showsHorizontalScrollIndicator={showScrollIndicator}
indicatorStyle={props.indicatorColor}
horizontal
// data={props.stackData || data}
keyExtractor={(item, index) => index.toString()}>
<Fragment>
{showVerticalLines &&
verticalLinesAr.map((item: itemType, index: number) => {
let totalSpacing = initialSpacing;
if (verticalLinesSpacing) {
totalSpacing = verticalLinesSpacing * (index + 1);
} else {
if (props.stackData) {
totalSpacing +=
(props.stackData[0].barWidth || props.barWidth || 30) / 2;
} else {
totalSpacing +=
(props.data[0].barWidth || props.barWidth || 30) / 2;
}
for (let i = 0; i < index; i++) {
let actualSpacing = spacing;
if (props.stackData) {
if (i >= props.stackData.length - 1) {
actualSpacing += (props.barWidth || 30) / 2;
} else {
if (
props.stackData[i].spacing ||
props.stackData[i].spacing === 0
) {
actualSpacing = props.stackData[i].spacing;
}
if (props.stackData[i + 1].barWidth) {
actualSpacing += props.stackData[i + 1].barWidth;
} else {
actualSpacing += props.barWidth || 30;
}
}
} else {
if (i >= props.data.length - 1) {
actualSpacing += (props.barWidth || 30) / 2;
} else {
if (
props.data[i].spacing ||
props.data[i].spacing === 0
) {
console.log('here for index ' + index + ' and i ' + i);
actualSpacing = props.data[i].spacing;
}
if (props.data[i + 1].barWidth) {
actualSpacing += props.data[i + 1].barWidth;
} else {
actualSpacing += props.barWidth || 30;
}
}
}
console.log('i = ' + i + ' actualSpacing ' + actualSpacing);
totalSpacing += actualSpacing;
}
}
return (
<View
key={index}
style={{
position: 'absolute',
zIndex: verticalLinesZIndex || -1,
marginBottom: xAxisThickness,
height:
verticalLinesHeight ||
containerHeight + 15 - xAxisThickness,
width: verticalLinesThickness,
backgroundColor: verticalLinesColor,
bottom: 60 + labelsExtraHeight,
left: totalSpacing,
}}
/>
);
})}
{showLine
? lineConfig.isAnimated
? renderAnimatedLine()
: renderLine()
: null}
{props.stackData
? props.stackData.map((item, index) => {
return (
<RenderStackBars
key={index}
stackData={props.stackData}
item={item}
index={index}
containerHeight={containerHeight}
maxValue={maxValue}
spacing={item.spacing === 0 ? 0 : item.spacing || spacing}
propSpacing={spacing}
xAxisThickness={xAxisThickness}
barWidth={props.barWidth}
opacity={opacity}
disablePress={item.disablePress || props.disablePress}
rotateLabel={rotateLabel}
showXAxisIndices={showXAxisIndices}
xAxisIndicesHeight={xAxisIndicesHeight}
xAxisIndicesWidth={xAxisIndicesWidth}
xAxisIndicesColor={xAxisIndicesColor}
horizontal={horizontal}
intactTopLabel={intactTopLabel}
barBorderRadius={props.barBorderRadius}
barBackgroundPattern={props.barBackgroundPattern}
patternId={props.patternId}
label={
item.label ||
(props.xAxisLabelTexts && props.xAxisLabelTexts[index]
? props.xAxisLabelTexts[index]
: '')
}
labelTextStyle={
item.labelTextStyle || props.xAxisLabelTextStyle
}
xAxisTextNumberOfLines={xAxisTextNumberOfLines}
renderTooltip={props.renderTooltip}
initialSpacing={initialSpacing}
selectedIndex={selectedIndex}
setSelectedIndex={setSelectedIndex}
activeOpacity={props.activeOpacity || 0.2}
/>
);
})
: data.map((item, index) => (
<RenderBars
key={index}
item={item}
index={index}
containerHeight={containerHeight}
maxValue={maxValue}
spacing={item.spacing === 0 ? 0 : item.spacing || spacing}
propSpacing={spacing}
side={side}
data={data}
barWidth={props.barWidth}
sideWidth={props.sideWidth}
labelWidth={labelWidth}
opacity={opacity}
isThreeD={isThreeD}
isAnimated={isAnimated}
animationDuration={animationDuration}
rotateLabel={rotateLabel}
animatedHeight={animatedHeight}
appearingOpacity={appearingOpacity}
roundedTop={props.roundedTop}
roundedBottom={props.roundedBottom}
disablePress={props.disablePress}
frontColor={props.frontColor}
sideColor={props.sideColor}
topColor={props.topColor}
showGradient={props.showGradient}
gradientColor={props.gradientColor}
activeOpacity={props.activeOpacity}
cappedBars={props.cappedBars}
capThickness={props.capThickness}
capColor={props.capColor}
capRadius={props.capRadius}
showXAxisIndices={showXAxisIndices}
xAxisIndicesHeight={xAxisIndicesHeight}
xAxisIndicesWidth={xAxisIndicesWidth}
xAxisIndicesColor={xAxisIndicesColor}
horizontal={horizontal}
intactTopLabel={intactTopLabel}
barBorderRadius={props.barBorderRadius}
autoShiftLabels={autoShiftLabels}
barBackgroundPattern={props.barBackgroundPattern}
patternId={props.patternId}
barMarginBottom={props.barMarginBottom}
label={
item.label ||
(props.xAxisLabelTexts && props.xAxisLabelTexts[index]
? props.xAxisLabelTexts[index]
: '')
}
labelTextStyle={
item.labelTextStyle || props.xAxisLabelTextStyle
}
onPress={props.onPress}
xAxisTextNumberOfLines={xAxisTextNumberOfLines}
renderTooltip={props.renderTooltip}
initialSpacing={initialSpacing}
selectedIndex={selectedIndex}
setSelectedIndex={setSelectedIndex}
/>
))}
</Fragment>
</ScrollView>
</View>
);
}
Example #25
Source File: DetailsHeader.tsx From RNChallenge_2 with MIT License | 4 votes |
DetailsHeader = ({
headerColor,
images,
id,
shared,
quandity = 0,
goToCart,
}: Props) => {
const {width, height} = useWindowDimensions();
const navigation = useNavigation();
const shakeAnim = useRef(new Animated.Value(0)).current;
useEffect(() => {
if (quandity > 0) {
shakeAnimation();
}
}, [quandity]);
const shakeAnimation = () => {
Animated.sequence([
Animated.timing(shakeAnim, {
toValue: 3,
duration: 100,
easing: Easing.cubic,
useNativeDriver: true,
}),
Animated.timing(shakeAnim, {
toValue: -3,
duration: 100,
easing: Easing.cubic,
useNativeDriver: true,
}),
Animated.timing(shakeAnim, {
toValue: 3,
duration: 100,
easing: Easing.cubic,
useNativeDriver: true,
}),
Animated.timing(shakeAnim, {
toValue: 0,
duration: 100,
easing: Easing.cubic,
useNativeDriver: true,
}),
]).start();
};
return (
<View>
<View
style={{
width: width * 0.5,
height: width * 0.5,
backgroundColor: headerColor,
top: -width * 0.1,
position: 'absolute',
left: -width * 0.25,
borderRadius: (width * 0.6) / 2,
transform: [{scaleX: 2.5}, {scaleY: 2.2}],
}}
/>
<View style={[styles.header]}>
<TouchableOpacity
onPress={() => {
navigation.goBack();
}}>
<Image
style={{
width: 22,
height: 22,
}}
source={require('../../Assets/Icons/back.png')}
/>
</TouchableOpacity>
<View
style={{
width: 70,
justifyContent: 'space-between',
alignItems: 'center',
flexDirection: 'row',
}}>
<TouchableOpacity onPress={() => goToCart()} style={[styles.likeBtn]}>
<Animated.View
style={[
styles.badge,
{
transform: [{translateX: shakeAnim}],
},
]}>
<Text
style={{
color: 'white',
fontSize: 5,
textAlign: 'center',
fontWeight: 'bold',
}}>
{quandity}
</Text>
</Animated.View>
<Image
style={{
width: 15,
height: 15,
}}
source={require('../../Assets/Icons/cart.png')}
/>
</TouchableOpacity>
<TouchableOpacity style={[styles.likeBtn]}>
<Image
style={{
width: 15,
height: 15,
}}
source={require('../../Assets/Icons/like.png')}
/>
</TouchableOpacity>
</View>
</View>
<Carousel
id={id}
shared={shared}
activeColor={headerColor}
backgroundColor={'transparent'}
offset={75}
height={height * 0.26}
images={images}
/>
</View>
);
}
Example #26
Source File: DownloadIcon.tsx From jellyfin-audio-player with MIT License | 4 votes |
function DownloadIcon({ trackId, size = 16, fill }: DownloadIconProps) {
// determine styles
const defaultStyles = useDefaultStyles();
const iconFill = fill || defaultStyles.textQuarterOpacity.color;
// Get download icon from state
const entity = useTypedSelector((state) => state.downloads.entities[trackId]);
const isQueued = useTypedSelector((state) => state.downloads.queued.includes(trackId));
// Memoize calculations for radius and circumference of the circle
const radius = useMemo(() => size / 2, [size]);
const circumference = useMemo(() => radius * 2 * Math.PI, [radius]);
// Initialize refs for the circle and the animated value
const circleRef = useRef<Circle>(null);
const offsetAnimation = useRef(new Animated.Value(entity?.progress || 0)).current;
// Whenever the progress changes, trigger the animation
useEffect(() => {
Animated.timing(offsetAnimation, {
toValue: (circumference * (1 - (entity?.progress || 0))),
duration: 250,
useNativeDriver: false,
easing: Easing.ease,
}).start();
}, [entity?.progress, offsetAnimation, circumference]);
// On mount, subscribe to changes in the animation value and then
// apply them to the circle using native props
useEffect(() => {
const subscription = offsetAnimation.addListener((offset) => {
// @ts-expect-error undocumented functionality
const setNativeProps = circleRef.current?.setNativeProps as (props: CircleProps) => void | undefined;
setNativeProps?.({ strokeDashoffset: offset.value });
});
return () => offsetAnimation.removeListener(subscription);
}, [offsetAnimation]);
if (!entity && !isQueued) {
return (
<CloudIcon width={size} height={size} fill={iconFill} />
);
}
if (entity?.isComplete) {
return (
<InternalDriveIcon width={size} height={size} fill={iconFill} />
);
}
if (entity?.isFailed) {
return (
<CloudExclamationMarkIcon width={size} height={size} fill={iconFill} />
);
}
if (isQueued || (!entity?.isFailed && !entity?.isComplete)) {
return (
<DownloadContainer>
<Svg width={size} height={size} transform={[{ rotate: '-90deg' }]}>
<Circle
cx={radius}
cy={radius}
r={radius - 1}
stroke={iconFill}
// @ts-expect-error react-native-svg has outdated react-native typings
ref={circleRef}
strokeWidth={1.5}
strokeDasharray={[ circumference, circumference ]}
strokeDashoffset={circumference}
strokeLinecap='round'
fill='transparent'
/>
</Svg>
<IconOverlay>
<CloudDownArrow width={size} height={size} fill={iconFill} />
</IconOverlay>
</DownloadContainer>
);
}
return null;
}
Example #27
Source File: FlutterwaveCheckout.tsx From flutterwave-react-native with MIT License | 4 votes |
FlutterwaveCheckout: React.FC<FlutterwaveCheckoutProps> = function FlutterwaveCheckout(props) {
const {link, visible, onRedirect, onAbort} = props;
const [show, setShow] = React.useState<boolean>(false);
const webviewRef = React.useRef<WebView | null>(null);
const animation = React.useRef<Animated.Value>(new Animated.Value(0));
const animateIn = React.useCallback(() => {
setShow(true);
Animated.timing(animation.current, {
toValue: 1,
duration: 700,
easing: Easing.in(Easing.elastic(0.72)),
useNativeDriver: false,
}).start();
}, []);
const animateOut = React.useCallback((): Promise<void> => {
return new Promise(resolve => {
Animated.timing(animation.current, {
toValue: 0,
duration: 400,
useNativeDriver: false,
}).start(() => {
setShow(false);
resolve();
});
})
}, []);
const handleReload = React.useCallback(() => {
if (webviewRef.current) {
webviewRef.current.reload();
}
}, []);
const handleAbort = React.useCallback((confirmed: boolean = false) => {
if (!confirmed) {
Alert.alert('', 'Are you sure you want to cancel this payment?', [
{text: 'No'},
{
text: 'Yes, Cancel',
style: 'destructive',
onPress: () => handleAbort(true),
},
]);
return;
}
// remove tx_ref and dismiss
animateOut().then(onAbort);
}, [onAbort, animateOut]);
const handleNavigationStateChange = React.useCallback((ev: WebViewNavigation): boolean => {
// cregex to check if redirect has occured on completion/cancel
const rx = /\/flutterwave\.com\/rn-redirect/;
// Don't end payment if not redirected back
if (!rx.test(ev.url)) {
return true;
}
// dismiss modal
animateOut().then(() => {
if (onRedirect) {
onRedirect(getRedirectParams(ev.url))
}
});
return false;
}, [onRedirect]);
const doAnimate = React.useCallback(() => {
if (visible === show) {
return;
}
if (visible) {
return animateIn();
}
animateOut().then(() => {});
}, [visible, show, animateOut, animateIn]);
React.useEffect(() => {
doAnimate();
return () => {};
}, [doAnimate]);
const marginTop = animation.current.interpolate({
inputRange: [0, 1],
outputRange: [windowHeight, 0],
});
const opacity = animation.current.interpolate({
inputRange: [0, 0.3, 1],
outputRange: [0, 1, 1],
});
return (
<Modal
transparent={true}
animated={false}
hardwareAccelerated={false}
visible={show}>
<FlutterwaveCheckoutBackdrop onPress={() => handleAbort()} animation={animation.current} />
<Animated.View
style={[
styles.webviewContainer,
{
marginTop,
opacity
}
]}
testID='flw-checkout-dialog'
>
<WebView
ref={webviewRef}
source={{uri: link || ''}}
style={styles.webview}
startInLoadingState={true}
scalesPageToFit={true}
javaScriptEnabled={true}
onShouldStartLoadWithRequest={handleNavigationStateChange}
renderError={() => <FlutterwaveCheckoutError hasLink={!!link} onTryAgain={handleReload} />}
renderLoading={() => <FlutterwaveCheckoutLoader />}
/>
</Animated.View>
</Modal>
)
}
Example #28
Source File: index.tsx From krmanga with MIT License | 4 votes |
function MangaView({
navigation, dispatch, isLogin, chapterList, bookInfo,
book_id, headerHeight, markRoast, chapter_num, episodeList, hasMore, loading,
currentChapterNum, pages
}: IProps) {
const [endReached, setEndReached] = useState<boolean>(false);
let [time, setTime] = useState<NodeJS.Timeout | null>(null);
let flatListRef: FlatList<IEpisode> | null = null;
const topPanelValue = useRef(new Animated.Value(0)).current;
const bottomPanelValue = useRef(new Animated.Value(0)).current;
const drawerX = useRef(new Animated.Value(-viewportWidth)).current;
let panelEnable: boolean = true;
useEffect(() => {
loadData(true);
return () => {
StatusBar.setHidden(false);
if (isLogin) {
dispatch({
type: "mangaView/addHistory",
payload: {
book_id
}
});
dispatch({
type: "history/setScreenReload"
});
dispatch({
type: "downloadManage/setScreenReload"
});
}
dispatch({
type: "mangaView/setState",
payload: {
...initialState
}
});
};
}, []);
const loadData = (refreshing: boolean, callback?: () => void) => {
dispatch({
type: "mangaView/fetchEpisodeList",
payload: {
refreshing,
markRoast,
chapter_num,
book_id
},
callback
});
};
const onEndReached = () => {
if (!hasMore || loading) {
return;
}
setEndReached(true);
dispatch({
type: "mangaView/fetchEpisodeList",
payload: {
book_id,
chapter_num: currentChapterNum + 1
},
callback: () => {
setEndReached(false);
}
});
};
const renderItem = ({ item }: ListRenderItemInfo<IEpisode>) => {
return (
<Item panelHandle={panelHandle} data={item} />
);
};
const renderFooter = () => {
if (endReached) {
return <More />;
}
if (!hasMore) {
return <End />;
}
return null;
};
const getItemLayout = (data: any, index: number) => {
if (data[index] === undefined) {
return { length: 0, offset: 0, index };
}
let offset = 0;
const length = viewportWidth * data[index].multiple;
for (let i = 0; i < index; i++) {
offset += viewportWidth * data[i].multiple;
}
return { length: length, offset, index };
};
const scrollToIndex = (index: number) => {
dispatch({
type: "brief/setState",
payload: {
markChapterNum: episodeList[index].chapter_num,
markRoast: episodeList[index].roast
}
});
flatListRef?.scrollToIndex({ viewPosition: 0, index: index });
};
const lastChapter = () => {
if (!loading) {
dispatch({
type: "mangaView/fetchEpisodeList",
payload: {
refreshing: true,
book_id,
chapter_num: currentChapterNum - 1
}
});
}
};
const nextChapter = () => {
if (!loading) {
dispatch({
type: "mangaView/fetchEpisodeList",
payload: {
refreshing: true,
book_id,
chapter_num: currentChapterNum + 1
}
});
}
};
const showDrawer = () => {
Animated.timing(drawerX, {
toValue: 0,
duration: 200,
useNativeDriver: true
}).start();
};
const hideDrawer = () => {
Animated.timing(drawerX, {
toValue: -viewportWidth,
duration: 200,
useNativeDriver: true
}).start();
};
const hidePanel = () => {
if (panelEnable) {
Animated.parallel([
Animated.timing(
topPanelValue,
{
toValue: -headerHeight - getStatusBarHeight(),
duration: 200,
easing: Easing.linear,
useNativeDriver: true
}
),
Animated.timing(
bottomPanelValue,
{
toValue: hp(25),
duration: 200,
easing: Easing.linear,
useNativeDriver: true
}
)
]).start(() => {
StatusBar.setHidden(true);
panelEnable = !panelEnable;
});
}
};
const showPanel = () => {
if (!panelEnable) {
Animated.parallel([
Animated.timing(
topPanelValue,
{
toValue: 0,
duration: 200,
easing: Easing.linear,
useNativeDriver: true
}
),
Animated.timing(
bottomPanelValue,
{
toValue: 0,
duration: 200,
easing: Easing.linear,
useNativeDriver: true
}
)
]).start(() => {
StatusBar.setHidden(false);
panelEnable = !panelEnable;
});
}
};
const panelHandle = useCallback(() => {
if (panelEnable) {
hidePanel();
} else {
showPanel();
}
}, [panelEnable]);
const debounce = (cb: any, wait = 250) => {
if (time !== null) {
clearTimeout(time);
}
let tempTime = setTimeout(() => {
time = null;
cb && cb();
}, wait);
setTime(tempTime);
};
const onScrollEndDrag = ({ nativeEvent }: NativeSyntheticEvent<NativeScrollEvent>) => {
let offset_total = 0;
let current_episode_total = episodeList[0].episode_total;
let current_chapter_id = episodeList[0].chapter_id;
let current_chapter_num = episodeList[0].chapter_num;
let current_number = episodeList[0].number;
let current_roast = episodeList[0].roast;
let current_title = episodeList[0].title;
for (let i = 0; i < episodeList.length; i++) {
if (nativeEvent.contentOffset.y >= offset_total) {
current_episode_total = episodeList[i].episode_total;
current_chapter_id = episodeList[i].chapter_id;
current_chapter_num = episodeList[i].chapter_num;
current_number = episodeList[i].number;
current_roast = episodeList[i].roast;
current_title = episodeList[i].title;
} else {
break;
}
offset_total = offset_total + episodeList[i].multiple * viewportWidth;
}
debounce(() => {
dispatch({
type: "mangaView/setState",
payload: {
currentEpisodeTotal: current_episode_total,
currentChapterId: current_chapter_id,
currentChapterNum: current_chapter_num,
currentNumber: current_number,
showCurrentNumber: current_number,
currentRoast: current_roast,
currentTitle: current_title
}
});
dispatch({
type: "brief/setState",
payload: {
markChapterNum: current_chapter_num,
markRoast: current_roast
}
});
});
hidePanel();
};
const goMangaChapter = useCallback((item: IChapter) => {
dispatch({
type: "mangaView/fetchEpisodeList",
payload: {
refreshing: true,
book_id,
chapter_num: item.chapter_num,
callback: () => hideDrawer
}
});
}, []);
return (
episodeList.length > 0 ?
<View>
<StatusBar barStyle="light-content" />
<TopCtrPanel
book_id={book_id}
topPanelValue={topPanelValue}
navigation={navigation}
/>
<BottomCtrPanel
bottomPanelValue={bottomPanelValue}
scrollToIndex={scrollToIndex}
showDrawer={showDrawer}
lastChapter={lastChapter}
nextChapter={nextChapter}
/>
<FlatList
ref={ref => (flatListRef = ref)}
data={episodeList}
keyExtractor={(item, key) => `item-${item.id}-key-${key}`}
renderItem={renderItem}
ListFooterComponent={renderFooter}
getItemLayout={getItemLayout}
onScrollEndDrag={onScrollEndDrag}
initialScrollIndex={pages.episode_offset - 1}
onEndReached={onEndReached}
onEndReachedThreshold={0.1}
extraData={endReached}
/>
<DarkDrawer
chapterList={chapterList}
bookInfo={bookInfo}
headerHeight={headerHeight}
drawerX={drawerX}
hideDrawer={hideDrawer}
goMangaView={goMangaChapter}
/>
<BottomStatusBar />
</View> : null
);
}
Example #29
Source File: index.tsx From tiktok-clone with MIT License | 4 votes |
Feed: React.FC<Props> = ({ play, item }) => {
const spinValue = new Animated.Value(0);
Animated.loop(
Animated.timing(spinValue, {
toValue: 1,
duration: 10000,
easing: Easing.linear,
useNativeDriver: true,
}),
).start();
const rotateProp = spinValue.interpolate({
inputRange: [0, 1],
outputRange: ['0deg', '360deg'],
});
return (
<>
<LinearGradient
colors={['rgba(0,0,0,.3)', 'transparent']}
style={{
position: 'absolute',
left: 0,
right: 0,
top: 0,
height: '70%',
}}
/>
<Container>
<Video
source={{ uri: item.uri }}
rate={1.0}
volume={1.0}
isMuted={false}
resizeMode="cover"
shouldPlay={play}
isLooping
style={{
width: '100%',
height: '100%',
}}
/>
</Container>
<Details>
<User>{item.username}</User>
<Tags>{item.tags}</Tags>
<MusicBox>
<FontAwesome name="music" size={15} color="#f5f5f5" />
<Music>{item.music}</Music>
</MusicBox>
</Details>
<Actions>
<BoxAction>
<AntDesign
style={{ alignSelf: 'center' }}
name="heart"
size={35}
color="#fff"
/>
<TextAction>{item.likes}</TextAction>
</BoxAction>
<BoxAction>
<FontAwesome
style={{ alignSelf: 'center' }}
name="commenting"
size={35}
color="#fff"
/>
<TextAction>{item.comments}</TextAction>
</BoxAction>
<BoxAction>
<FontAwesome
style={{ alignSelf: 'center' }}
name="whatsapp"
size={35}
color="#06d755"
/>
<TextAction>Share</TextAction>
</BoxAction>
<BoxAction>
<Animated.View
style={{
borderRadius: 50,
borderWidth: 12,
borderColor: '#292929',
transform: [
{
rotate: play ? rotateProp : 0,
},
],
}}
>
<Image
style={{
width: 35,
height: 35,
borderRadius: 25,
}}
source={{
uri: 'https://avatars3.githubusercontent.com/u/45601574',
}}
/>
</Animated.View>
<Lottie
source={musicFly}
progress={play ? spinValue : 0}
style={{ width: 150, position: 'absolute', bottom: 0, right: 0 }}
/>
</BoxAction>
</Actions>
<LinearGradient
colors={['transparent', 'rgba(0,0,0,.4)']}
style={{
position: 'absolute',
left: 0,
right: 0,
bottom: 0,
height: '50%',
}}
/>
</>
);
}