Skip to content

Latest commit

 

History

History
274 lines (222 loc) · 5.32 KB

File metadata and controls

274 lines (222 loc) · 5.32 KB

Circle Gestures

step2.MP4

Step 1 – Add tap gesture to the knob

step1.mov
[1] Create a `Gesture.Tap` and apply it to the `knob` view using `GestureDetector`
const tapGesture = Gesture.Tap()

<GestureDetector gesture={tapGesture}>
  <Animated.View style={styles.knob} />
</GestureDetector>

[2] `tapGesture` should set a scale value based on which we are going to animate the knob. When gesture ends, we are bringing back the scale to the initial value
create a `scale` sharedValue starting from 1
const scale = useSharedValue(1);

add onBegin method and change `scale` value using spring
.onBegin(() => {
  scale.value = withSpring(2)
})

add onEnd method to bring back the scale to using spring
.onEnd(() => {
  scale.value = withSpring(1)
})

create a knobStyle using useAnimatedStyle and change the scale and borderWidth by interpolating scale.value `[1,2] → [layout.knobSize / 2, 2]`
const animatedStyle = useAnimatedStyle(() => {
  return {
    borderWidth: interpolate(
      scale.value,
      [1, 2],
      [layout.knobSize / 2, 2],
      Extrapolation.CLAMP
    ),
    transform: [
      {
        scale: scale.value,
      },
    ],
  };
});

apply this style to the knob
<Animated.View style={[styles.knob, animatedStyle]} hitSlop={hitSlop} />


Step 2 – Add pan gesture to the knob

step2.MP4

Create a Pan gesture, combine it with Tap gesture. Using Pan gesture, we can get the x coordinate of the pan, assign it to a sharedValue that's starting from 0 and use this to apply the knob translateX position.

[1] let’s use the same principle and create a `Gesture.Pan`
const panGesture = Gesture.Pan();

[2] `panGesture` should set a `x` value based on which we are going to move/animate the knob. When gesture ends, we are bringing back the `x` to the initial value (0)
create a `x` sharedValue starting from 1
const x = useSharedValue(0);

add onChange method and change x value based on `changeX`
.onChange((ev) => {
  x.value += ev.changeX
})

⚠️ TIP: The reason why we’re using changeX instead of translationX is that we would like to start from where we left when the gesture is triggered again (aka when we start panning again), in other words it keeps the knob in place and next time will move from the current position


when gesture has finished, bring back the knob `scale` to 1.
.onEnd(() => {
  scale.value = withSpring(1)
})

apply `transform.translateX` as style using `x` shared value
const animatedStyle = useAnimatedStyle(() => {
  return {
    borderWidth: //
    transform: [
      {
        translateX: x.value  // <--------- here
      },
      {
        scale: scale.value,
      },
    ],
  }
})

[3] Add both `Tap` and `Pan` as simulataneous gestures and apply it to the `GestureDetector`
const gestures = Gesture.Simultaneous(tapGesture, panGesture)

<GestureDetector gesture={gestures}>
  //
</GestureDetector>



Step 3 - Only with Pan gesture

step1.mov

remove tapGesture and use just the panGesture as gesture on GestureDetector. Create an isInteracting shared value and replace the scale with a derivedValue that's going to animate using withSpring() based on isInteracting value.

[1] Create an `isInteracting` shared value and replace the `scale` with a `derivedValue` that's going to animate using `withSpring()` based on `isInteracting` value.
create isInteracting value and replace scale with a derived value.
const isInteracting = useSharedValue(false);
const scale = useDerivedValue(() => {
  return withSpring(isInteracting.value ? 2 : 1);
});

using `.onBegin` and `.onFinalize` to toggle `isInteractive` value
.onBegin(() => {
  isInteracting.value = true
})
.onFinalize(() => {
  isInteracting.value = false
})

using `.onEnd` to bring back `x` to the initial value
.onEnd(() => {
  x.value = withSpring(0)
})

Next step

Go to: Balloon Slider