2017-03-03 92 views
1

林試圖讓兩個圓圈,可以拖動,並與反應天然下降。反應本地拖放多個項目

我已創建了一個循環,可以拖放,但不知道如何與單獨兩個圓。

這裏是一個循環,可以拖放,

constructor(props){ 
    super(props); 
    this.state = { 
     pan  : new Animated.ValueXY() //Step 1 
    }; 

    this.panResponder = PanResponder.create({ //Step 2 
     onStartShouldSetPanResponder :() => true, 
     onPanResponderMove   : Animated.event([null,{ //Step 3 
      dx : this.state.pan.x, 
      dy : this.state.pan.y 
     }]), 

     onPanResponderRelease  : (e, gesture) => {} //Step 4 
    }); 
} 

的代碼,這是圖像

renderDraggable(){ 
return (
    <View style={styles.draggableContainer}> 
     <Animated.View 
      {...this.panResponder.panHandlers} 
      style={[this.state.pan.getLayout(), styles.circle]}> 
      <Text style={styles.text}>Drag me!</Text> 
     </Animated.View> 
    </View> 
); 
} 

回答

0
import React, { Component } from 'react'; 

import { 
StyleSheet, 
Text, 
View, 
Image, // we want to use an image 
PanResponder, // we want to bring in the PanResponder system 
Animated // we wil be using animated value 
} from 'react-native'; 

export default class Tag extends React.Component { 

constructor(props) { 
    super(props); 

    this.state = { 
    pan: new Animated.ValueXY(), 
    scale: new Animated.Value(1) 
    }; 
} 
_handleStartShouldSetPanResponder(e, gestureState) { 
    return true; 
} 

_handleMoveShouldSetPanResponder(e, gestureState) { 
return true; 
} 

componentWillMount() { 
    this._panResponder = PanResponder.create({ 
    onStartShouldSetPanResponder: 
    this._handleStartShouldSetPanResponder.bind(this), 
    onMoveShouldSetPanResponder: 
    this._handleMoveShouldSetPanResponder.bind(this), 

    onPanResponderGrant: (e, gestureState) => { 
    // Set the initial value to the current state 
    this.state.pan.setOffset({x: this.state.pan.x._value, y: this.state.pan.y._value}); 
    this.state.pan.setValue({x: 30*Math.random(), y: 0}); 
    Animated.spring(
     this.state.scale, 
     { toValue: 1.1, friction: 1 } 
    ).start(); 
    }, 

    // When we drag/pan the object, set the delate to the states pan position 
    onPanResponderMove: Animated.event([ 
    null, {dx: this.state.pan.x, dy: this.state.pan.y}, 
    ]), 

    onPanResponderRelease: (e, {vx, vy}) => { 
    // Flatten the offset to avoid erratic behavior 
    this.state.pan.flattenOffset(); 
    Animated.spring(
     this.state.scale, 
     { toValue: 1, friction: 1 } 
    ).start(); 
    } 
    }); 
    } 

    render() { 
// Destructure the value of pan from the state 
let { pan, scale } = this.state; 

// Calculate the x and y transform from the pan value 
let [translateX, translateY] = [pan.x, pan.y]; 

let rotate = '0deg'; 
// Calculate the transform property and set it as a value for our style which we add below to the Animated.View component 
let imageStyle = {transform: [{translateX}, {translateY}, {rotate}, {scale}]}; 

return (
    <Animated.View style={[imageStyle, styles.container]} {...this._panResponder.panHandlers} > 
    <View style={styles.rect}> 
     <Text style={styles.txt} >tgyyHH</Text> 
     </View> 
    </Animated.View> 
); 
} 

} 

const styles = StyleSheet.create({ 
    container: { 
    width:50, 
    height:50, 
    position: 'absolute' 
}, 
rect: { 
    borderRadius:4, 
    borderWidth: 1, 
    borderColor: '#fff', 
    width:50, 
    height:50, 
    backgroundColor:'#68a0cf', 

    }, 
    txt: { 
    color:'#fff', 
    textAlign:'center' 
    } 

}); 
+0

您好感謝您的評論。這是非常有幫助的,但是如何製作兩個可以分開移動的不同圖像? –

0

這裏是相互獨立的是如何製成的物品。這個例子是打字稿,但應足夠清楚,轉換爲純JavaScript。這裏的主要思想是每個動畫項目需要自己PanResponderInstance,一旦你更新的項目,您還需要刷新PanResponderInstance

interface State { 
    model: Array<MyAnimatedItem>, 
    pans: Array<Animated.ValueXY>, 
    dropZone1: LayoutRectangle, 
    dropZone2: LayoutRectangle, 
} 

public render(): JSX.Element { 

    const myAnimatedItems = new Array<JSX.Element>() 
    for (let i = 0; i < this.state.model.length; i++) { 
     const item = this.state.model[i] 
     const inst = this.createResponder(this.state.pans[i], item) 
     myAnimatedItems.push(
      <Animated.View 
       key={'item_' + i} 
       {...inst.panHandlers} 
       style={this.state.pans[i].getLayout()}> 
       <Text>{item.description}</Text> 
      </Animated.View> 
     ) 
    } 

    return (
     <View> 
      <View onLayout={this.setDropZone1} style={styles.dropZone}> 
       <View style={styles.draggableContainer}> 
        {myAnimatedItems} 
       </View> 
      </View> 
      <View onLayout={this.setDropZone2} style={styles.dropZone}> 
       <View style={styles.draggableContainer}> 
        ... 
       </View> 
      </View> 
     </View> 
    ) 
} 

private setDropZone1 = (event: LayoutChangeEvent): void => { 
    this.setState({ 
     dropZone1: event.nativeEvent.layout 
    }) 
} 

private setDropZone2 = (event: LayoutChangeEvent): void => { 
    this.setState({ 
     dropZone2: event.nativeEvent.layout 
    }) 
} 

private isDropZone(gesture: PanResponderGestureState, dropZone: LayoutRectangle): boolean { 
    const toolBarHeight = variables.toolbarHeight + 15 // padding 
    return gesture.moveY > dropZone.y + toolBarHeight 
     && gesture.moveY < dropZone.y + dropZone.height + toolBarHeight 
     && gesture.moveX > dropZone.x 
     && gesture.moveX < dropZone.x + dropZone.width 
} 

private createResponder(pan: Animated.ValueXY, item: MyAnimatedItem): PanResponderInstance { 
    return PanResponder.create({ 
     onStartShouldSetPanResponder:() => true, 
     onPanResponderMove: Animated.event([null, { 
      dx: pan.x, 
      dy: pan.y 
     }]), 
     onPanResponderRelease: (_e, gesture: PanResponderGestureState) => { 
      const model = this.state.model 
      const pans = this.state.pans 
      const idx = model.findIndex(x => x.id === item.id) 

      if (this.isDropZone(gesture, this.state.dropZone1)) { 
       ... // do something with the item if needed 
       // reset each PanResponderInstance 
       for (let i = 0; i < model.length; i++) { 
        pans[i] = new Animated.ValueXY() 
       } 
       this.setState({ model: model, pans: pans }) 
       return 
       } 
      } else if (this.isDropZone(gesture, this.state.dropZone2)) { 
       ... // do something with the item if needed 
        // reset each PanResponderInstance 
       for (let i = 0; i < model.length; i++) { 
        pans[i] = new Animated.ValueXY() 
       } 
       this.setState({ model: model, pans: pans }) 
       return 
      } 

      Animated.spring(pan, { toValue: { x: 0, y: 0 } }).start() 
      this.setState({ scrollEnabled: true }) 
     } 
    }) 
}