diff --git a/MotionAnimator.podspec b/MotionAnimator.podspec index c6416f1..960e137 100644 --- a/MotionAnimator.podspec +++ b/MotionAnimator.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "MotionAnimator" - s.summary = "Motion Animator" + s.summary = "A Motion Animator creates performant, interruptible animations from motion specs." s.version = "1.0.0" s.authors = "The Material Motion Authors" s.license = "Apache 2.0" diff --git a/README.md b/README.md index 5592639..c66d61d 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,59 @@ # Motion Animator +> A Motion Animator creates performant, interruptible animations from motion specs. + [![Build Status](https://travis-ci.org/material-motion/motion-animator-objc.svg?branch=develop)](https://travis-ci.org/material-motion/motion-animator-objc) [![codecov](https://codecov.io/gh/material-motion/motion-animator-objc/branch/develop/graph/badge.svg)](https://codecov.io/gh/material-motion/motion-animator-objc) -[![CocoaPods Compatible](https://img.shields.io/cocoapods/v/motion-animator.svg)](https://cocoapods.org/pods/motion-animator) -[![Platform](https://img.shields.io/cocoapods/p/motion-animator.svg)](http://cocoadocs.org/docsets/motion-animator) -[![Docs](https://img.shields.io/cocoapods/metrics/doc-percent/motion-animator.svg)](http://cocoadocs.org/docsets/motion-animator) +[![CocoaPods Compatible](https://img.shields.io/cocoapods/v/MotionAnimator.svg)](https://cocoapods.org/pods/MotionAnimator) +[![Platform](https://img.shields.io/cocoapods/p/MotionAnimator.svg)](http://cocoadocs.org/docsets/MotionAnimator) +[![Docs](https://img.shields.io/cocoapods/metrics/doc-percent/MotionAnimator.svg)](http://cocoadocs.org/docsets/MotionAnimator) + +This library turns [Motion Interchange](https://github.com/material-motion/motion-interchange-objc) +data structures into performant Core Animation animations using a lightweight animator object. + + + +In the above example we're animating the expansion and collapse of a calendar event using the +following motion specification: + +```objc +struct CalendarChipTiming { + MDMMotionTiming chipWidth; + MDMMotionTiming chipHeight; + MDMMotionTiming chipY; + + MDMMotionTiming chipContentOpacity; + MDMMotionTiming headerContentOpacity; + + MDMMotionTiming navigationBarY; +}; +typedef struct CalendarChipTiming CalendarChipTiming; + +struct CalendarChipMotionSpec { + CalendarChipTiming expansion; + CalendarChipTiming collapse; +}; +typedef struct CalendarChipMotionSpec CalendarChipMotionSpec; + +FOUNDATION_EXTERN struct CalendarChipMotionSpec CalendarChipSpec; +``` + +In our application logic, we first determine which motion timing to use and then we create an +instance of `MDMMotionAnimator`. The animator allows us to create animations with the given +motion timing. + +```objc +CalendarChipTiming timing = _expanded ? CalendarChipSpec.expansion : CalendarChipSpec.collapse; + +MDMMotionAnimator *animator = [[MDMMotionAnimator alloc] init]; +animator.shouldReverseValues = !_expanded; + +[animator animateWithTiming:timing.chipHeight + toLayer:chipView.layer + withValues:@[ @(chipFrame.size.height), @(headerFrame.size.height) ] + keyPath:MDMKeyPathHeight]; +... +``` ## Installation @@ -19,7 +68,7 @@ Add `motion-animator` to your `Podfile`: - pod 'motion-animator' + pod 'MotionAnimator' Then run the following command: @@ -29,7 +78,7 @@ Then run the following command: Import the framework: - @import motion-animator; + @import MotionAnimator; You will now have access to all of the APIs. @@ -41,16 +90,56 @@ commands: git clone https://github.com/material-motion/motion-animator-objc.git cd motion-animator-objc pod install - open motion-animator.xcworkspace + open MotionAnimator.xcworkspace ## Guides 1. [Architecture](#architecture) -2. [How to ...](#how-to-...) +2. [How to animate a transition](#how-to-animate-a-transition) +3. [How to animate an interruptible transition](#how-to-animate-an-interruptible-transition) ### Architecture -### How to ... +`MDMMotionAnimator` is the primary API provided by this library and its external API is fairly +straight forward. Once an instance is created, you can configure its behavior by modifying its +properties. When you're ready to add an animation to a CALayer instance, simply call one of the +`animate` method variants and an animation will instantly be added to the layer. + +This library depends on [MotionInterchange](https://github.com/material-motion/motion-interchange-objc) +in order to represent motion timing in a consistent fashion. + +### How to animate a transition + +> This guide assumes that you are animating a two state bi-directional transition. + +Start by creating an `MDMMotionAnimator` instance. + +```objc +MDMMotionAnimator *animator = [[MDMMotionAnimator alloc] init]; +``` + +When we describe our transition we'll describe it as though we're moving forward and take advantage +of the `shouldReverseValues` property on our animator to handle the reverse direction. + +```objc +animator.shouldReverseValues = isTransitionReversed; +``` + +To animate a property on a view, we invoke the `animate` method. We must provide a timing, values, +and a key path: + +```objc +[animator animateWithTiming:timing + toLayer:view.layer + withValues:@[ @(collapsedHeight), @(expandedHeight) ] + keyPath:MDMKeyPathHeight]; +``` + +### How to animate an interruptible transition + +`MDMMotionAnimator` is configured by default to generate interruptible animations using Core +Animation's additive animation APIs. You can simply re-execute the `animate` calls when your +transition's direction changes and the animator will add new animations for the updated direction. ## Contributing diff --git a/assets/calendar-chip.gif b/assets/calendar-chip.gif new file mode 100644 index 0000000..5268819 Binary files /dev/null and b/assets/calendar-chip.gif differ