Course Menu

Drag Square

Drag Square Animation

Alright, we learned about moving squares, interpolating colors, interpolating on rotation. Now lets combine them and add a drag.

The main concept here is the drag, but we'll see some usage of Dimensions which helps us get the device dimensions so we can adjust our interpolations to the draggable areas.

import React from "react";
import {
  StyleSheet,
  Text,
  View,
  PanResponder,
  Animated,
  Dimensions,
} from "react-native";

const { height: deviceHeight, width: deviceWidth } = Dimensions.get("window");

const SampleApp = React.createClass({
  componentWillMount: function () {
    this._animatedValue = new Animated.ValueXY();
    this._value = { x: 0, y: 0 };

    this._animatedValue.addListener((value) => (this._value = value));
    this._panResponder = PanResponder.create({
      onMoveShouldSetResponderCapture: () => true, //Tell iOS that we are allowing the movement
      onMoveShouldSetPanResponderCapture: () => true, // Same here, tell iOS that we allow dragging
      onPanResponderGrant: (e, gestureState) => {
        this._animatedValue.setOffset({ x: this._value.x, y: this._value.y });
        this._animatedValue.setValue({ x: 0, y: 0 });
      },
      onPanResponderMove: Animated.event([
        null,
        { dx: this._animatedValue.x, dy: this._animatedValue.y },
      ]), // Creates a function to handle the movement and set offsets
      onPanResponderRelease: () => {
        this._animatedValue.flattenOffset(); // Flatten the offset so it resets the default positioning
      },
    });
  },
  render: function () {
    const interpolatedColorAnimation = this._animatedValue.y.interpolate({
      inputRange: [0, deviceHeight - 100],
      outputRange: ["rgba(229,27,66,1)", "rgba(90,146,253,1)"],
      extrapolate: "clamp",
    });

    const interpolatedRotateAnimation = this._animatedValue.x.interpolate({
      inputRange: [0, deviceWidth / 2, deviceWidth],
      outputRange: ["-360deg", "0deg", "360deg"],
    });

    return (
      <View style={styles.container}>
        <Animated.View
          style={[
            styles.box,
            {
              transform: [
                { translateX: this._animatedValue.x },
                { translateY: this._animatedValue.y },
                { rotate: interpolatedRotateAnimation },
              ],
              backgroundColor: interpolatedColorAnimation,
            },
          ]}
          {...this._panResponder.panHandlers}
        />
      </View>
    );
  },
});

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: "center",
    justifyContent: "center",
  },
  box: {
    width: 100,
    height: 100,
  },
});