react-native-lucy-radial-slider
Version:
React Native component to select or highlight a specific value from a range of values
109 lines • 4.95 kB
JavaScript
import { useEffect, useRef, useState } from 'react';
import { PanResponder, } from 'react-native';
import { cartesianToPolar, getCurrentRadian, getRadianByValue, polarToCartesian, } from '../../../utils/commonHelpers';
import useRadialSlider from './useRadialSlider';
const useSliderAnimation = (props) => {
const { step = 1, radius = 100, sliderWidth = 18, thumbRadius = 18, thumbBorderWidth = 5, disabled, min = 0, onChange = () => { }, max = 100, onComplete = () => { }, startAngle = 270, variant = 'default', } = props;
let moveStartValue;
let startCartesian;
let moveStartRadian;
const { radianValue } = useRadialSlider(props);
const prevValue = useRef(props.value > min ? props.value : min);
const [value, setValue] = useState((props === null || props === void 0 ? void 0 : props.value) < min ? min : (props === null || props === void 0 ? void 0 : props.value) > max ? max : props === null || props === void 0 ? void 0 : props.value);
useEffect(() => {
if (max < (props === null || props === void 0 ? void 0 : props.value)) {
setValue(max);
}
else if (min > (props === null || props === void 0 ? void 0 : props.value)) {
setValue(min);
}
}, [max, min]);
useEffect(() => {
if (min <= (props === null || props === void 0 ? void 0 : props.value) && max >= (props === null || props === void 0 ? void 0 : props.value)) {
setValue(props === null || props === void 0 ? void 0 : props.value);
prevValue.current = props === null || props === void 0 ? void 0 : props.value;
}
}, [props === null || props === void 0 ? void 0 : props.value]);
// useEffect(() => {
// onChange(value);
// prevValue.current = value;
// }, [value]);
const handlePanResponderGrant = () => {
moveStartValue = prevValue.current;
moveStartRadian = getRadianByValue(prevValue.current, radianValue, max, min);
startCartesian = polarToCartesian(moveStartRadian, radius, sliderWidth, thumbRadius, thumbBorderWidth, startAngle, variant);
return true;
};
const handlePanResponderMove = (_e, gestureState) => {
if (disabled) {
return;
}
let { x, y } = startCartesian;
x += gestureState.dx;
y += gestureState.dy;
const radian = cartesianToPolar(x, y, radius, sliderWidth, thumbRadius, thumbBorderWidth, startAngle, variant);
const ratio = (moveStartRadian - radian) / ((Math.PI - radianValue) * 2);
const diff = max - min;
let nValue;
if (step) {
nValue = moveStartValue + Math.round((ratio * diff) / step) * step;
}
else {
nValue = moveStartValue + ratio * diff;
}
nValue = Math.max(min, Math.min(max, nValue));
setValue((prevState) => {
const roundedValue = parseFloat(nValue.toFixed(1));
prevValue.current =
Math.abs(roundedValue - prevState) > diff / 4
? prevState
: roundedValue;
return Math.abs(roundedValue - prevState) > diff / 4
? prevState
: roundedValue;
});
onChange(prevValue.current);
};
const onCompleteRef = useRef(onComplete);
useEffect(() => {
onCompleteRef.current = onComplete;
}, [onComplete]);
const handlePanResponderEnd = () => {
if (disabled) {
return;
}
onCompleteRef.current(prevValue.current);
};
const panResponder = useRef(PanResponder.create({
onStartShouldSetPanResponder: () => true,
onMoveShouldSetPanResponder: () => false,
onPanResponderGrant: handlePanResponderGrant,
onPanResponderMove: handlePanResponderMove,
onPanResponderRelease: handlePanResponderEnd,
onPanResponderTerminationRequest: () => false,
onPanResponderTerminate: handlePanResponderEnd,
}));
useEffect(() => {
panResponder.current = PanResponder.create({
onStartShouldSetPanResponder: () => true,
onMoveShouldSetPanResponder: () => false,
onPanResponderGrant: handlePanResponderGrant,
onPanResponderMove: handlePanResponderMove,
onPanResponderRelease: handlePanResponderEnd,
onPanResponderTerminationRequest: () => false,
onPanResponderTerminate: handlePanResponderEnd,
});
}, [min, max, disabled]);
const currentRadian = getCurrentRadian(value, radianValue, max, min);
const curPoint = polarToCartesian(currentRadian, radius, sliderWidth, thumbRadius, thumbBorderWidth, startAngle, variant);
return {
panResponder: panResponder.current,
prevValue,
value,
setValue,
curPoint,
currentRadian,
};
};
export default useSliderAnimation;
//# sourceMappingURL=useSliderAnimation.js.map