material-motion / material-motion-swift

A toolkit for building responsive motion using Core Animation.
Apache License 2.0
1.42k stars 79 forks source link

Explore a gesture type that only emits T-value types #76

Open jverkoey opened 7 years ago

jverkoey commented 7 years ago

Gesture recognizers currently emit themselves along the stream's next channel, meaning we need operators like whenRecognitionStateIs and translationIn in order to extract values from the object.

I'd like to make gesture streams closer in shape to spring/tween streams in that they'd have specific streams for translation and velocity that could be subscribed to. For example, an API for a gesture recognizer interaction might look like so:

class PanGesture: Interaction {
  func velocityStream(in: UIView) -> MotionObservable<CGPoint>
  func translationStream(in: UIView) -> MotionObservable<CGPoint>

  let stateStream: MotionObservable<UIGestureRecognizerState>

  let state: ReactiveProperty<MotionState> // .active when .began/.changed, .atRest otherwise
  let enabled: ReactiveProperty<Bool> // Maps to the gesture recognizer's enabled property

  func add(to property: ReactiveProperty<CGPoint>, ...)
}

let pan = PanGesture()

// Like Draggable. Draggable might compose out to this interaction as a convenience API for making views draggable.
runtime.add(pan, to: runtime.get(view.layer).position)

// Getting final velocity:
let didEnd = pan.stateStream.rewrite([.ended: true], otherwise: false)
let velocityOnRelease = pan.velocityStream(in: someView).valve(openWhenTrue: didEnd)
runtime.connect(velocityOnRelease, to: spring.initialVelocity)