Artem Bochkarev
Artem Bochkarev

Reputation: 1350

Rotate Icon around another Icon

There is no transform-origin property in react-native so how can I do it ? I think I should use transformX & transformY props.

  const Marker = () => {
    const rotate = new Animated.Value(???);
    const transformX = new Animated.Value(???);
    const transformY = new Animated.Value(???);

    const doRotation = (newDegValue) => {
      // ?????
    }
    return (
      <View style={{ width: 200, height: 200, justifyContent: 'center', alignItems: 'center' }}>
        <Animated.View transform={[{ rotate }, { transformX }, { transformY }]}>
          <ArrowIcon width={30} height={30}>
        </Animated.View>
        {/* I need to rotate my ArrowIcon around this BaseIcon */}
        <BaseIcon width={100} height={100} /> 
      <View/>
    )
  }

need behaviour like this

Upvotes: 3

Views: 1905

Answers (2)

Tim
Tim

Reputation: 10709

Explanation

In this example, I am using the Animated Library. First, we are defining a Animated Value in the constructor. Then we are creating a triggerAnimation function, where we will animate this new value over time using the timing function.

In the render function, we are defining a new style object called animatedStyle. This style object will handle the rotation of the arrow. We are using the interpolate function to incrementally rotate the arrow. As inputRange we are allowing -1 to +1. -1 means a rotation of -360° and +1 a rotation of 360°-, as you can see in the outputRange.The interpolate function will automatically handle the mapping between input and output range.

In the return statement we are passing the animatedStyle to our <Animated.View>.

Now we can call the triggerAnimation function. As parameter we have to pass the desired rotation value.

Some Examples:
this.triggerAnimation(0.5) would result in a rotation of +180°.

this.triggerAnimation(-0.5) would result in a rotation of -180°.

this.triggerAnimation(0.25) would result in a rotation of +90°.

this.triggerAnimation(0.75) would result in a rotation of +270°.

Code

Constructor and triggerAnimation function:

constructor(props){
    super(props);
    this.state={
      currentRotation: 0, 
      value: new Animated.Value(0),
    }
  }

  triggerAnimation(newValue){
    Animated.timing(this.state.value, {
      toValue: newValue,
      duration: 500,
    }).start(() => {
      // set rotated again
      this.setState({currentRotation: newValue})
    });
  }

render function:

render() {
const animatedStyle={
  transform: [
    {
      rotateZ: this.state.value.interpolate({ 
      inputRange: [-1,1],
      outputRange: ['-360deg', `360deg`],
      }),
    },
  ],
};
return (
  <View style={styles.container}>
  <View style={{justifyContent: 'center', flexDirection: 'column', alignItems: 'center', width: 150, height: 150}}>
    <Animated.View style={[{justifyContent: 'center', flexDirection: 'row', alignItems: 'flex-start'}, StyleSheet.absoluteFill,animatedStyle]} >
      <Icon name={"location-arrow"} size={30} style={{transform: [ {rotateZ: '-45deg' }]}}/>
    </Animated.View>
    <View style={{width: 70, height: 70, borderRadius: 35, backgroundColor: 'blue'}}/>
  </View>

    <TouchableOpacity onPress={()=>this.triggerAnimation(0.5)} >
      <Text> 180° Trigger Animation </Text>
    </TouchableOpacity>
     ...
  </View>
);
}

Working Demo

https://snack.expo.io/B1UzO79Cr

Upvotes: 2

Pramod
Pramod

Reputation: 1940

You can use transform: [{ rotate: '40deg' }] in styles

Example: => https://snack.expo.io/@msbot01/mad-cookie

export default class App extends React.Component {
  constructor(props){
    super(props)

    this.state=({
      angle:0
    })

  }

  rotate(){
    this.setState({
      angle: this.state.angle + 5
    })
  }

  render() {
    return (
      <View style={styles.container}>
        <TouchableOpacity onPress={()=>{this.rotate()}} style={{position: "absolute", top:20, width:'100%'}}>
          <Text style={{marginTop:20, position:'absolute', top:20}}>Click on me to rotate</Text>    
        </TouchableOpacity >
        <Image style={{height:40, width:40}} source={require('./bus.png')} />
        <View onPress={()=>{this.rotate()}} style={{position: "absolute"}}>
          <Image style={{height:150, width:150, transform: [{ rotate: (this.state.angle+'deg') }]}} source={require('./ss.png')} />    
        </View >


      </View>
    );
  }
}

Upvotes: 1

Related Questions