From 21fc28207a2febf08fcad3ea64e2f5060cc12da5 Mon Sep 17 00:00:00 2001 From: Vitalij Lutsyk Date: Sun, 3 Jul 2022 20:20:47 +0300 Subject: [PATCH] feat: add startFromZero (#344) --- src/index.tsx | 70 +++++++++++++++++++++++++++++++----------- src/stories/Slider.tsx | 20 ++++++++++++ src/types.ts | 5 +++ 3 files changed, 77 insertions(+), 18 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 0b4bd25..bd50181 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -187,6 +187,7 @@ export class Slider extends PureComponent { trackClickable: true, value: 0, vertical: false, + startFromZero: false, }; static getDerivedStateFromProps(props: SliderProps, state: SliderState) { @@ -198,9 +199,7 @@ export class Slider extends PureComponent { const newTrackMarkValues = normalizeValue(props, props.trackMarks); const statePatch = {} as SliderState; - if ( - state.trackMarksValues - ) { + if (state.trackMarksValues) { statePatch.trackMarksValues = updateValues({ values: state.trackMarksValues, newValues: newTrackMarkValues, @@ -358,13 +357,19 @@ export class Slider extends PureComponent { const standardRatio = this._getRatio(value); const ratio = I18nManager.isRTL ? 1 - standardRatio : standardRatio; - return ratio * ((vertical ? containerSize.height : containerSize.width) - thumbSize.width); + return ( + ratio * + ((vertical ? containerSize.height : containerSize.width) - + thumbSize.width) + ); }; - _getValue = (gestureState: {dx: number, dy: number}) => { + _getValue = (gestureState: {dx: number; dy: number}) => { const {containerSize, thumbSize, values} = this.state; const {maximumValue, minimumValue, step, vertical} = this.props; const length = containerSize.width - thumbSize.width; - const thumbLeft = vertical ? this._previousLeft + (gestureState.dy * -1) : this._previousLeft + gestureState.dx; + const thumbLeft = vertical + ? this._previousLeft + gestureState.dy * -1 + : this._previousLeft + gestureState.dx; const nonRtlRatio = thumbLeft / length; const ratio = I18nManager.isRTL ? 1 - nonRtlRatio : nonRtlRatio; let minValue = minimumValue; @@ -617,6 +622,8 @@ export class Slider extends PureComponent { thumbTintColor, trackStyle, vertical, + startFromZero, + step = 0, ...other } = this.props; const { @@ -626,6 +633,10 @@ export class Slider extends PureComponent { trackMarksValues, values, } = this.state; + const _startFromZero = + values.length === 1 && minimumValue < 0 && maximumValue > 0 + ? startFromZero + : false; const interpolatedThumbValues = values.map((value) => value.interpolate({ inputRange: [minimumValue, maximumValue], @@ -659,31 +670,50 @@ export class Slider extends PureComponent { const interpolatedRawValues = this._getRawValues( interpolatedTrackValues, ); + const minRawValue = Math.min(...interpolatedRawValues); + const minThumbValue = new Animated.Value(minRawValue); + const maxRawValue = Math.max(...interpolatedRawValues); + const maxThumbValue = new Animated.Value(maxRawValue); + + const _value = values[0].__getValue(); + const sliderWidthCoefficient = + containerSize.width / + (Math.abs(minimumValue) + Math.abs(maximumValue)); + const startPositionOnTrack = _startFromZero + ? _value < 0 + step + ? (_value + Math.abs(minimumValue)) * sliderWidthCoefficient + : Math.abs(minimumValue) * sliderWidthCoefficient + : 0; + + const minTrackWidth = _startFromZero + ? Math.abs(_value) * sliderWidthCoefficient - thumbSize.width / 2 + : interpolatedTrackValues[0]; + const clearBorderRadius = {} as ViewStyle; + if (_startFromZero && _value < 0 + step) { + clearBorderRadius.borderBottomRightRadius = 0; + clearBorderRadius.borderTopRightRadius = 0; + } + if (_startFromZero && _value > 0) { + clearBorderRadius.borderTopLeftRadius = 0; + clearBorderRadius.borderBottomLeftRadius = 0; + } - const minThumbValue = new Animated.Value( - Math.min(...interpolatedRawValues), - ); - const maxThumbValue = new Animated.Value( - Math.max(...interpolatedRawValues), - ); const minimumTrackStyle = { position: 'absolute', left: interpolatedTrackValues.length === 1 - ? new Animated.Value(0) + ? new Animated.Value(startPositionOnTrack) : Animated.add(minThumbValue, thumbSize.width / 2), width: interpolatedTrackValues.length === 1 - ? Animated.add( - interpolatedTrackValues[0], - thumbSize.width / 2, - ) + ? Animated.add(minTrackWidth, thumbSize.width / 2) : Animated.add( Animated.multiply(minThumbValue, -1), maxThumbValue, ), backgroundColor: minimumTrackTintColor, ...valueVisibleStyle, + ...clearBorderRadius, } as ViewStyle; const touchOverflowStyle = this._getTouchOverflowStyle(); @@ -717,7 +747,11 @@ export class Slider extends PureComponent { )} ( + + + + + + ; trackStyle?: ViewStyle; value?: Animated.Value | number | Array; + /** + * Allows the start from the zero value. The minimum value track can be rendered in two directions from zero. + * Can be applied only with a single numeric value, negative minimum value, and positive maximum value. + */ + startFromZero?: boolean; vertical?: boolean; };