Skip to content

Instantly share code, notes, and snippets.

@dilipsuthar97
Created August 5, 2022 08:37
Show Gist options
  • Save dilipsuthar97/83eb3bbe6c1c8eef1af5c188d1e12900 to your computer and use it in GitHub Desktop.
Save dilipsuthar97/83eb3bbe6c1c8eef1af5c188d1e12900 to your computer and use it in GitHub Desktop.
// --------------- LIBRARIES ---------------
import React, { memo } from 'react';
import { View, Animated, StyleSheet, Easing, PanResponder } from 'react-native';
// --------------- ASSETS ---------------
export const TRACK_HEIGHT = 32;
export const HOR_PAD = 10;
const Colors = {
OVERLAY_LIGHT_30: 'rgba(255,255,255,0.3)',
OVERLAY_LIGHT_40: 'rgba(255,255,255,0.4)',
OVERLAY_LIGHT_70: 'rgba(255,255,255,0.7)',
TRANSPARENT: 'rgba(0,0,0,0.0)',
PRIMARY: 'rgb(252, 70, 119)'
}
const SeekBar = React.forwardRef((props, ref) => {
// --------------- VARS ---------------
const progress = React.useRef(new Animated.Value(0)).current;
/**
* To remove stale closure effect we have used useRef hook to store value
* because state and normal var values will not updated inside stale closure effect.
* Learn more about stale closure here:
* https://dmitripavlutin.com/react-hooks-stale-closures/
*/
const isFullScreen = React.useRef(props.isFullScreen);
const seekbarWidth = React.useRef(0);
const progressWidth = progress.interpolate({
inputRange: [0, 1],
outputRange: ['0%', '100%'],
extrapolate: 'clamp',
});
const thumbPosition = progress.interpolate({
inputRange: [0, 1],
outputRange: [0, 16],
extrapolate: 'clamp',
});
const panResponder = React.useRef(
PanResponder.create({
onStartShouldSetPanResponder: () => true,
onMoveShouldSetPanResponder: () => true,
onPanResponderGrant: (e) => {
const seekProgress = e.nativeEvent.locationX / seekbarWidth.current;
props.onSeekBarTouch(seekProgress);
progress.setValue(seekProgress);
},
onPanResponderStart: (e, gestureState) => {},
onPanResponderMove: (e, gestureState) => {
const seekProgress = e.nativeEvent.locationX / seekbarWidth.current;
props.onSeekBarMove(seekProgress);
progress.setValue(seekProgress);
},
onPanResponderRelease: (e) => {
const seekProgress = e.nativeEvent.locationX / seekbarWidth.current;
props.onSeekBarRelease(seekProgress);
progress.setValue(seekProgress);
},
}),
).current;
// --------------- EXPOSE METHODS ---------------
React.useImperativeHandle(ref, () => ({
setProgress,
}));
// --------------- EVENTS ---------------
React.useEffect(() => {
isFullScreen.current = props.isFullScreen;
}, [props.isFullScreen]);
// --------------- METHODS ---------------
/**
* Function to animate seekbar progress on video/music progress from 0 to 100%
*/
const setProgress = (toProgress = 0, duration = 300) => {
Animated.timing(progress, {
toValue: toProgress,
duration,
useNativeDriver: false,
easing: Easing.linear,
}).start();
};
return (
<Animated.View
onLayout={(e) => {
seekbarWidth.current = e.nativeEvent.layout.width;
}}
style={[styles.container, props.style]}
>
<Animated.View style={styles.wrapper} {...panResponder.panHandlers}>
<View
style={[styles.track, { backgroundColor: props.trackColor }]}
pointerEvents={'none'}
>
<Animated.View
style={[
styles.fill,
{
width: progressWidth,
},
{ backgroundColor: props.progressColor },
]}
pointerEvents={'none'}/>
<Animated.View
style={[
styles.thumb,
{ transform: [{ translateX: thumbPosition }] },
{ backgroundColor: props.thumbColor },
]}
pointerEvents={'none'}/>
</View>
</Animated.View>
</Animated.View>
);
});
SeekBar.defaultProps = {
progressColor: 'rgb(252, 70, 119)',
trackColor: Colors.OVERLAY_LIGHT_30,
thumbColor: 'white',
thumbScale: 1,
thumbActiveScale: 1.2,
removeBaseWidth: 0,
};
export default memo(SeekBar);
const styles = StyleSheet.create({
container: {
height: TRACK_HEIGHT,
flex: 1,
},
wrapper: {
justifyContent: 'center',
position: 'absolute',
left: 0,
right: 0,
height: '100%',
backgroundColor: Colors.TRANSPARENT,
},
track: {
height: 4,
width: '100%',
position: 'relative',
flexDirection: 'row',
alignItems: 'center',
},
fill: {
height: 4,
},
thumb: {
width: 16,
height: 16,
borderRadius: 50,
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment