I created a "circle bar" (group of views) that switch from grey to yellow as the images move. The circles start to transform correctly but then go back to the first spot instead of going to the next circle spot to indict that you are on the next image. The yellow circle just always goes back to the first spot no matter what. Does anyone know why this might be happening?? How do I get it to stay in the next spot?
PLEASE see this video that I made of it: https://youtu.be/BCaSgNexPAs
Here is how I create and handle the circle view transformations:
let circleArray = []; if (this.state.imgArray) { this.state.imgArray.forEach((val, i) => { const scrollCircleVal = this.imgXPos.interpolate({ inputRange: [deviceWidth * (i - 1), deviceWidth * (i + 1)], outputRange: [-8, 8], extrapolate: 'clamp', }); const thisCircle = ( <View key={'circle' + i} style={[ styles.track, { width: 8, height: 8, marginLeft: i === 0 ? 0 : CIRCLE_SPACE, borderRadius: 75 }, ]} > <Animated.View style={[ styles.circle, { width: 8, height: 8, borderRadius: 75, transform: [ {translateX: scrollCircleVal}, ], backgroundColor: '#FFD200' }, ]} /> </View> ); circleArray.push(thisCircle) }); }
And here's my code for how I handle the image swiping:
handleSwipe = (indexDirection) => { if (!this.state.imgArray[this.state.imgIndex + indexDirection]) { Animated.spring(this.imgXPos, { toValue: 0 }).start(); return; } this.setState((prevState) => ({ imgIndex: prevState.imgIndex + indexDirection }), () => { this.imgXPos.setValue(indexDirection * this.width); Animated.spring(this.imgXPos, { toValue: 0 }).start(); }); } imgPanResponder = PanResponder.create({ onStartShouldSetPanResponder: () => true, onPanResponderMove: (e, gs) => { this.imgXPos.setValue(gs.dx); }, onPanResponderRelease: (e, gs) => { this.width = Dimensions.get('window').width; const direction = Math.sign(gs.dx); if (Math.abs(gs.dx) > this.width * 0.4) { Animated.timing(this.imgXPos, { toValue: direction * this.width, duration: 250 }).start(() => this.handleSwipe(-1 * direction)); } else { Animated.spring(this.imgXPos, { toValue: 0 }).start(); } } });
Html:
<Animated.Image {...this.imgPanResponder.panHandlers} key={'image' + this.state.imgIndex} style={{left: this.imgXPos, height: '100%', width: '100%', borderRadius: 7}} resizeMethod={'scale'} resizeMode={'cover'} source={{uri: this.state.imgArray[this.state.imgIndex]}} /> <View style={styles.circleContainer}> {circleArray} </View>
2 Answers
Answers 1
It's hard to get your code at first as it's all in the same spot.
I would first suggest breaking your code into smaller parts: ImageView, CirclesView
Now after we got that done, I would want to try to make the CirclesView a bit simpler (unless you really want this animation view inside the circle).
But from your code, I didn't see the difference for the "selectedImage" (imgIndex)
As it has calculations for each index, but with no reference to the selected image.
Rough ballpark code I would think to do with the current code:
let circleArray = []; if (this.state.imgArray) { this.state.imgArray.forEach((val, i) => { const scrollCircleVal = this.imgXPos.interpolate({ inputRange: [deviceWidth * (i - 1), deviceWidth * (i + 1)], outputRange: [-8, 8], extrapolate: 'clamp', }); const thisCircle = ( <View key={'circle' + i} style={[ styles.track, { width: 8, height: 8, marginLeft: i === 0 ? 0 : CIRCLE_SPACE, borderRadius: 75 }, ]} > // LOOK AT THIS LINE BELOW {this.state.imgIndex == i && <Animated.View style={[ styles.circle, { width: 8, height: 8, borderRadius: 75, transform: [ {translateX: scrollCircleVal}, ], backgroundColor: '#FFD200' }, ]} />} </View> ); circleArray.push(thisCircle) }); }
checkout the line I added above the "animated" circle for the "selected" circle
Answers 2
I would agree with most of Tzook notices ... but from what I see in code (intentions) all circles are animated (but in fact only one pair affected - one hides, one shows) - animating only selected one doesn't give that.
I animated hundreds 'sliders/galleries' in flash ;) - what with prev/next/neighborh images - shouldn't be animated at the same time?
Images with the same width (or when you can accept margins between them) are easy, you can animate container with 3 (or even only 2) images from longer (looped of course?) list/array. It's like virtual list scrolling.
Having this working circles will be easy, too - animate only 3 of them: prev/curr/next ones.
Simple animations are easy - only swapping images at the end of animation. It could look harder with f.e. bouncing effects (when image slides more/farther than it's target position and next img should be visible for a while) but you can just swap them earlier, just after recognizing direction.
0 comments:
Post a Comment