Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Corrected Slider Behavior #43

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 50 additions & 21 deletions ColorPicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ const flipInterpolationConfig = {
module.exports = class ColorPicker extends Component {
// testData = {}
// testView = {forceUpdate(){}}
sliderXOffset = 0
sliderYOffset = 0
color = { h: 0, s: 0, v: 100 }
slideX = new Animated.Value(0)
slideY = new Animated.Value(0)
Expand All @@ -178,6 +180,7 @@ module.exports = class ColorPicker extends Component {
discrete: false, // use swatches of shades instead of slider
discreteLength: 10, // number of swatches of shades, should be > 1
sliderHidden: false, // if true the slider is hidden
sliderHitSlop: 0, //defines how far the touch event can move away from the slider once started
swatches: true, // show color swatches
swatchesLast: true, // if false swatches are shown before wheel
swatchesOnly: false, // show swatch only and hide wheel and slider
Expand Down Expand Up @@ -244,9 +247,9 @@ module.exports = class ColorPicker extends Component {
onStartShouldSetPanResponderCapture: (event, gestureState) => {
if (this.props.disabled) return false;
const { nativeEvent } = event
if (this.outOfSlider(nativeEvent)) return
this.sliderMovement(event, gestureState)
this.updateValue({ nativeEvent })
const adjusted = this.sliderThumbAdjuster(event)
this.sliderMovement(adjusted, gestureState)
this.updateValue(adjusted)
return true
},
onStartShouldSetPanResponder: () => true,
Expand All @@ -265,8 +268,9 @@ module.exports = class ColorPicker extends Component {
if (this.props.disabled) return;
if (event && event.nativeEvent && typeof event.nativeEvent.preventDefault == 'function') event.nativeEvent.preventDefault()
if (event && event.nativeEvent && typeof event.nativeEvent.stopPropagation == 'function') event.nativeEvent.stopPropagation()
if (this.outOfSlider(event.nativeEvent) || this.outOfBox(this.sliderMeasure, gestureState)) return;
this.sliderMovement(event, gestureState)
if (this.outOfBox(this.sliderMeasureAdjuster(this.props.sliderHitSlop), gestureState)) return;
const adjusted = this.sliderThumbAdjuster(event)
this.sliderMovement(adjusted, gestureState)
},
onMoveShouldSetPanResponder: () => true,
onPanResponderRelease: (event, gestureState) => {
Expand Down Expand Up @@ -418,23 +422,44 @@ module.exports = class ColorPicker extends Component {
outOfBox(measure, gestureState) {
const { x, y, width, height } = measure
const { moveX, moveY, x0, y0 } = gestureState
// console.log(`${moveX} , ${moveY} / ${x} , ${y} / ${locationX} , ${locationY}`);
// console.log(`${moveX} , ${moveY} / ${x} , ${y} / `);
return !(moveX >= x && moveX <= x + width && moveY >= y && moveY <= y + height)
}
outOfWheel(nativeEvent) {
const { radius } = this.polar(nativeEvent)
return radius > 1
}
outOfSlider(nativeEvent) {
const row = this.props.row
const loc = row ? nativeEvent.locationY : nativeEvent.locationX
const { width, height } = this.sliderMeasure
return (loc > (row ? height - width : width - height))
}
val(v) {
const d = this.props.discrete, r = 11 * Math.round(v / 11)
return d ? (r >= 99 ? 100 : r) : v
}
sliderThumbAdjuster(event) {
const sliderThumbSize = this.props.sliderSize
const row = this.props.row
let correctedTouch = row ? event.nativeEvent.pageY : event.nativeEvent.pageX
correctedTouch -= sliderThumbSize/2
correctedTouch -= row ? this.sliderMeasure.y : this.sliderMeasure.x
const min = row ? this.sliderYOffset : this.sliderXOffset
const max = row ? this.sliderYOffset + this.sliderLength : this.sliderXOffset + this.sliderLength
if(correctedTouch < min)
correctedTouch = min;
else if(correctedTouch > max)
correctedTouch = max
return {nativeEvent: {
locationX: row ? event.nativeEvent.locationX : correctedTouch,
locationY: row ? correctedTouch : event.nativeEvent.locationY,
}}
}
sliderMeasureAdjuster(hitSlop) {
const row = this.props.row
const {x, y, width, height} = this.sliderMeasure
return {
x: row ? x - hitSlop : x,
y: row ? y : y - hitSlop,
width: row ? width + hitSlop*2 : width,
height: row ? height : height + hitSlop*2,
}
}
ratio(nativeEvent) {
const row = this.props.row
const loc = row ? nativeEvent.locationY : nativeEvent.locationX
Expand Down Expand Up @@ -705,16 +730,20 @@ module.exports = class ColorPicker extends Component {
</View>}
</View>}
{!swatchesOnly && !sliderHidden && (discrete
? <View style={[ss.swatches, swatchStyle]} key={'$2'}>{this.disc}</View>
: <View style={[ss.slider, sliderStyle]} key={'$2'}>
<View style={[ss.grad, { backgroundColor: hex }]} key={'$2$1'}>
<Image style={[ss.sliderImg, { opacity: !this.props.sliderLoadingIndicator || this.state.sliderImageLoaded ? 1 : 0 }]} source={row ? srcSliderRotated : srcSlider} onLoad={this.onSliderImageLoad} resizeMode="stretch" />
</View>
{(this.props.sliderLoadingIndicator ? this.state.sliderImageLoaded : true) && <Animated.View style={[ss.sliderThumb, sliderThumbStyle, Elevations[4], { pointerEvents: 'none' }]} key={'$2$2'} />}
<View style={[ss.cover]} key={'$2$3'} onLayout={this.onSliderLayout} {...sliderPanHandlers} ref={r => { this.slider = r }}>
{!!this.props.sliderLoadingIndicator && !this.state.sliderImageLoaded && this.props.sliderLoadingIndicator}
? <View style={[ss.swatches, swatchStyle]} key={'$2'}>{this.disc}</View>
: <View style={[ss.slider, sliderStyle]} key={'$2'} onLayout={event => {
const dimens = event.nativeEvent.layout;
this.sliderXOffset = dimens.x;
this.sliderYOffset = dimens.y;
}}>
<View style={[ss.grad, { backgroundColor: hex }]} key={'$2$1'}>
<Image style={[ss.sliderImg, { opacity: !this.props.sliderLoadingIndicator || this.state.sliderImageLoaded ? 1 : 0 }]} source={row ? srcSliderRotated : srcSlider} onLoad={this.onSliderImageLoad} resizeMode="stretch" />
</View>
{(this.props.sliderLoadingIndicator ? this.state.sliderImageLoaded : true) && <Animated.View style={[ss.sliderThumb, sliderThumbStyle, Elevations[4], { pointerEvents: 'none' }]} key={'$2$2'} />}
<View style={[ss.cover]} key={'$2$3'} onLayout={this.onSliderLayout} {...sliderPanHandlers} ref={r => { this.slider = r }}>
{!!this.props.sliderLoadingIndicator && !this.state.sliderImageLoaded && this.props.sliderLoadingIndicator}
</View>
</View>
</View>
)}
{swatches && swatchesLast && <View style={[ss.swatches, swatchStyle]} key={'SW'}>{this.swatches}</View>}
</View>
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,9 @@ export default App

`discreteLength: 10` number of swatches of shades, should be > 1

`sliderHidden: false` if true the slider is hidden
`sliderHidden: false` if true the slider is hidden

`sliderHitSlop: 0` defines how far the touch event can move away from the slider once started

`swatches: true` show color swatches

Expand Down