GithubHelp home page GithubHelp logo

maxprig / flightanimator Goto Github PK

View Code? Open in Web Editor NEW

This project forked from antonthedev/flightanimator

0.0 2.0 0.0 404 KB

Advanced Natural Motion Animations, Simple Blocks Based Syntax

License: Other

Swift 99.28% Ruby 0.43% Objective-C 0.29%

flightanimator's Introduction

#FlightAnimator

Cocoapods Compatible Carthage compatible ![Platform](https://img.shields.io/badge/platform-ios | tvos-lightgrey.svg) License

alt tag

##Introduction

FlightAnimator is a natural animation engine built on top of CoreAnimation, and provides a very simple blocks based syntax to create, configure, cache, and reuse animations dynamically.

A unique feature toFlightAnimator is that you can group multiple animations, and apply different easing curves per property. FlightAnimator takes care of the rest to synchronize them accordingly to create some very interesting effects :)

##Features

  • 46+ Parametric Curves, Decay, and Springs
  • Blocks Syntax for Building Complex Animations
  • Chain Animations:
    • Synchronously
    • Time Progress Relative
    • Value Progress Relative
  • Apply Unique Easing per Property Animation
  • Advanced Multi-Curve Group Synchronization
  • Define, Cache, and Reuse Animations

FlightAnimatore Demo

##Installation

##Communication

  • If you found a bug, or have a feature request, open an issue.
  • If you need help or a general question, use Stack Overflow. (tag 'flight-animator')
  • If you want to contribute, review the Contribution Guidelines, and submit a pull request.

##Basic Use

There are a many ways to use FlightAnimator as it provides a very flexible syntax for defining animations ranging in completexy with ease. Whether performing an animation, chaining animations, or registering/caching an animation, the framework follows a common blocks based builder approach to define property animations within an animation group. Each property animation, is configured with final value, and easing curve, and optionally the primary flag to adjust synchronization of the animations within a group when applied to the layer.

Under the hood animations are built as CAAnimationGroup(s) with multiple custom CAKeyframeAnimation(s) defined uniquely per property. Once it's time to animate, FlightAnimator will dynamically synchronize the remaining progress for all the animations relative to the current presentationLayer's values, then continue to animate to it's final state.

Check out the Framework Demo App to experiment with all the different capabilities of FlightAnimator.

###Simple Animation

To perform a simple animation call the animate(:) method on the view to animate. Once the animator completes the creation process, the animation applies itself on it's own to the layer, and sets all the final layers values on the model layer.

view.animate { (animator) in
      animator.bounds(newBounds).duration(0.5).easing(.OutCubic)
      animator.position(newPositon).duration(0.5).easing(.InSine)
}

The closure returns an instance FlightAnimator used to build a complex animation to perform one property at a time. Technically the animator creates a CGAnimationGroup under the hood to add individual animations to. Once inside the closure, the first step is to creating individual property animation with a destination value, then configure the duration, and easing curve accordingly.

Methods on the FlightAnimator defined for every supported animatable property, but In the case there is a need to animate a custom defined NSManaged animatable property, i.e progress to draw a circle. Use the value(value:forKeyPath:) method on the animator to animate that property.

view.animate { (animator) in
    animator.value(value, forKeyPath : "progress").duration(0.5).easing(.OutCubic)    
}

Once you have created a property animation within the group, it recursively returns an instance of PropertyAnimationConfig, which allows for chaining the a duration, easing curve, or primary flag, documentated documented at a later point in the documentation.

func duration(duration : CGFloat) -> PropertyAnimationConfig
func easing(easing : FAEasing) -> PropertyAnimationConfig
func primary(primary : Bool) -> PropertyAnimationConfig

###Animation Delegate Callbacks

If there is a need to implement the CAAnimationDelegate, you can directly apply the callbacks on the animator instance during creation.

view.animate { (animator) in
    animator.bounds(newBounds).duration(0.5).easing(.OutCubic)
    animator.position(newPositon).duration(0.5).easing(.InSine)
    
    animator.setDidStartCallback({ (anim) in
         // Animation Did Start
    })
    
    animator.setDidStopCallback({ (anim, complete) in
         // Animation Did Stop   
    })
}

##Chaining Animations

Chaining animations together in FlightAnimator is simple easy. You can nest animations using three different types triggers:

  • Simultaneously
  • Time Progress Based
  • Value Progress Based

These can be applied to the view being animated, or any other view accessible in the view heirarchy.

####Trigger Simultaneously

To trigger an animation right as the parent animation begins, attach a trigger on a parent animator by calling animator.triggerOnStart(...). The trigger will perform the animation enclosed accordingly right as the parent begins animating.

// Parent Animation Group
view.animate { (animator) in
	animator.bounds(newBounds).duration(0.5).easing(.EaseOutCubic)
    animator.position(newPositon).duration(0.5).easing(.EaseOutCubic)
    
    // Child Animation Group, Triggered by Parent Group
    animatortriggerOnStart(onView: self.secondaryView, animator: { (animator) in
         animator.bounds(newSecondaryBounds).duration(0.5).easing(.OutCubic)
         animator.position(newSecondaryCenter).duration(0.5).easing(.OutCubic)
    })
}

####Trigger Relative to Time Progress

A time based trigger will apply the next animation based on the progressed time of the overall parent animation. The progress value is defined with a range from 0.0 - 1.0, if the over all time of an animation is 1.0 second, by setting the atProgress paramter to 0.5, will trigger the animation at the 0.5 seconds into the parent animation.

Below is an examples that will trigger the second animation at the halfway point in time of the parent animation by calling triggerAtTimeProgress(...)

view.animate { (animator) in
	animator.bounds(newBounds).duration(0.5).easing(.OutCubic)
    animator.position(newPositon).duration(0.5).easing(.OutCubic)
    
    animator.triggerAtTimeProgress(atProgress: 0.5, onView: self.secondaryView, animator: { (animator) in
         animator.bounds(newSecondaryBounds).duration(0.5).easing(.OutCubic)
         animator.position(newSecondaryCenter).duration(0.5).easing(.OutCubic)
    })
}

####Trigger Relative to Value Progress

A value based progress trigger will apply the next animation based on the value progress of the overall parent animation. Below is an examples that will trigger the second animation at the halfway point of the value progress on the parent animation by calling animator.triggerAtValueProgress(...)

view.animate { (animator) in
	animator.bounds(newBounds).duration(0.5).easing(.EaseOutCubic)
    animator.position(newPositon).duration(0.5).easing(.EaseOutCubic)
    
    animator.triggerAtValueProgress(atProgress: 0.5, onView: self.secondaryView, animator: { (animator) in
         animator.bounds(newSecondaryBounds).duration(0.5).easing(.OutCubic)
         animator.position(newSecondaryCenter).duration(0.5).easing(.OutCubic)
    })
}

##Cache & Reuse Animations

FlighAnimator allows for registering animations (aka states) up front with a unique animation key. Once defined it can be manually triggered at any time in the application flow using the animation key used registration.

When the animation is applied, if the view is in mid flight, it will synchronize itself with the current presentation layer values, and animate to its final destination.

####Register/Cache Animation

To register an animation, call a globally defined method, and create an animations just as defined earlier examples within the maker block. The following example shows how to register, and cache an animation for a key on a specified view.

struct AnimationKeys {
	static let CenterStateFrameAnimation  = "CenterStateFrameAnimation"
}
...

registerAnimation(onView : view, forKey : AnimationKeys.CenterStateFrameAnimation) { (animator) in
      animator.bounds(newBounds).duration(0.5).easing(.OutCubic)
      animator.position(newPositon).duration(0.5).easing(.OutCubic)
})

This animation is only cached, and is not performed until it is manually triggered.

####Apply Registered Animation

To trigger the animation call the following

view.applyAnimation(forKey: AnimationKeys.CenterStateFrameAnimation)

To apply final values without animating the view, override the default animated flag to false, and it will apply all the final values to the model layer of the associated view.

view.applyAnimation(forKey: AnimationKeys.CenterStateFrameAnimation, animated : false)

##Advanced Use

###Timing Adjustments

Due to the dynamic nature of the framework, it may take a few tweaks to get the animation just right.

FlightAnimator has a few options for finer control over timing synchronization:

  • Timing Priority - Adjust how the time is select during synchronization of the overall animation
  • Primary Drivers - Defines animations that affect timing during synchronization of the overall animation

####Timing Priority

First a little background, the framework basically does some magic so synchronize the time by prioritizing the maximum time remaining based on progress if redirected in mid flight.

Lets look at the following example of setting the timingPriority on a group animation to .MaxTime, which is the default value for FlightAnimator.

func animateView(toFrame : CGRect) {
	
	let newBounds = CGRectMake(0,0, toFrame.width, toFrame.height)
	let newPosition = CGPointMake(toFrame.midX, toFrame.midY)
	
	view.animate(.MaxTime) { (animator) in
      	animator.bounds(newBounds).duration(0.5).easing(.OutCubic)
      	animator.position(newPositon).duration(0.5).easing(.InSine)
	}
}

Just like the demo app, This method gets called by different buttons, and takes on the frame value of button that triggered the method. Let's the animation has been triggered, and is in mid flight. While in mid flight another button is tapped, a new animation is applied, and ehe position changes, but the bounds stay the same.

Internally the framework will figure out the current progress in reference to the last animation, and will select the max duration value from the array of durations on the grouped property animations.

Lets assume the bounds don't change, thus animation's duration is assumed to be 0.0 after synchronization. The new animation will synchronize to the duration of the position animation based on progress, and automatically becomes the max duration based on the .MaxTime timing priority.

The timing priority can also be applied on triggerAtTimeProgress() or triggerAtValueProgress(). Now this leads into the next topic, and that is the primary flag.

The more property animations within a group, the more likely the need to adjust how the timing is applied. For this purpose there are 4 timing priorities to choose from:

  • .MaxTime
  • .MinTime
  • .Median
  • .Average

####Primary Flag

As in the example prior, there is a mention that animations can get quite complex, and the more property animations within a group, the more likely the animation will have a hick-up in the timing, especially when synchronizing 4+ animations with different curves and durations.

For this purpose, set the primary flag on individual property animations, and designate them as primary duration drivers. By default, if no property animation is set to primary, during synchronization, FlightAnimator will use the timing priority setting to find the corresponding value from all the animations after progress synchronization.

If we need only some specific property animations to define the progress accordingly, and become the primary drivers, set the primary flag to true, which will exclude any other animation which is not marked as primary from consideration.

Let's look at an example below of a simple view that is being animated from its current position to a new frame using bounds and position.

view.animate(.MaxTime) { (animator) in
      animator.bounds(newBounds).duration(0.5).easing(.OutCubic).primary(true)
      animator.position(newPositon).duration(0.5).easing(.InSine).primary(true)
      animator.alpha(0.0).duration(0.5).easing(.OutCubic)
      animator.transform(newTransform).duration(0.5).easing(.InSine)
}

Simple as that, now when the view is redirected during an animation in mid flight, only the bounds and position animations will be considered as part of the timing synchronization.

###.SpringDecay w/ Initial Velocity

When using a UIPanGestureRecognizer to move a view around on the screen by adjusting its position, and say there is a need to smoothly animate the view to the final destination right as the user lets go of the gesture. This is where the .SpringDecay easing comes into play. The .SpringDecay easing will slow the view down easily into place, all that need to be configured is the initial velocity, and it will calculate its own time relative to the velocity en route to its destination.

Below is an example of how to handle the handoff and use .SpringDecay(velocity: velocity) easing to perform the animation.

func respondToPanRecognizer(recognizer : UIPanGestureRecognizer) {
    switch recognizer.state {
    ........
    
    case .Ended:
    	let currentVelocity = recognizer.velocityInView(view)
        
      	view.animate { (animator) in
         	animator.bounds(finalBounds).duration(0.5).easing(.OutCubic)
  			animator.position(finalPositon).duration(0.5).easing(.SpringDecay(velocity: velocity))
      	}
    default:
        break
    }
}

##Reference

Supported Parametric Curves

CALayer's Supported Animatable Property

Current Release Notes

Contribution Guidelines

###Framework Demo App

The project includes a highly configurable demo app that allows for experimentation to explore resulting effects of the unlimited configurations FlightAnimator supports.

Demo Features Included:

  • Animate a view to different location on the screen
  • Drag and release view to apply Decay easing to the final destination
  • Adjust timing curves for bounds, position, alpha, and transform.
  • Enable a secondary view, which follows the main view to it's last location
  • Adjust group timing priority to test synchronization
  • Adjust progress for time based/value based triggers on the secondary view

License

FlightAnimator is released under the MIT license. See License for details.

flightanimator's People

Contributors

antonthedev avatar vsouza avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.