Parallax Scroll-Jacking Effects Engine for iOS / tvOS

Overview

Parade

Build Status codecov.io Carthage compatible Cocoapods Compatible Platform License

Introduction

Communicating to cells inside of UICollectionViews, UITableViews, or UIScrollViews, has always been a challenge. It almost always relies on a messy process of trying to relay the scroll to progress to cells in triggering special scrolling effects. We’ve designed this framework to minimize the effort needed to animate views. With a simple blocks-based builder we’ve made it easy to define view states—from where they appear and where they will disappear to.

Features

  • Supports UICollectionView, UITableView, UIScrollview
  • Simple Blocks-Based Syntax
  • Minimal Integration Requirements
  • Supports Chaining Animatable Views
  • Adjustable Progress Ranges
  • 46 Different Parametric Curves

Interactive Demo

There is a demo app included as part of the project that contains the following implemented examples for the following scrolling effects within the animated gif below.

Included Examples
alt tag The demo contains a single ParallaxImageViewController as the root, and displays these cells as examples in the following order:

- ParallaxIntroCollectionViewCell : Scale / Transform / Alpha

- ParallaxScaleCollectionViewCell : Scale / Center

- ParallaxDoubleImageCollectionViewCell : Center / Transform

- ParallaxImageAppearCollectionViewCell : Animation Chain Parallax

- ParallaxImageCollectionViewCell : Scale / Alpha / Transform

- ParallaxTheEndCollectionViewCell : Transform 3D

Note: The examples also contain custom ranges discussed later in the documentation.

Installation

Communication

  • If you found a bug, or have a feature request, open an issue.
  • If you want to contribute, review the Contribution Guidelines, and submit a pull request.
  • If you contribute, please ensure that the there is 100% code coverage

Basic Use

At its core, this framework defines start and end states for your animatable views—with the scroll view interpolating between the states accordingly. The start state defines where views appear from as they scroll onto screen—while end state defines where views will disappear.

The only requirements beyond defining the states is to implement the PDAnimatableType on views to animate, the rest is seamless. Each animation consists of a start or end state which is defined by the developer—plus a snapshot state that is automatically configured the first time the view begins to scroll.

Before creating, consider the diagram below to get a sense of the coordinate space that the progress is calculated against. Progress is relative to the bounds of the scrollview itself. When scrolling horizontally—the difference in X value to the center point of the viewport is equal to the width of the scrollview itself. Just as the difference in Y value when scrolling vertically, as demonstrated below.

alt tag

NOTE : There is control to adjust these ranges, and instructions can be found in the Bounding Progress Range section below.

Initialization

Initialize the Parade in application(:didFinishLaunchingWithOptions:) when the application is launched. Once initialized, the base UIScrollView will begin communicating scrolling progress to animatable views contained within.

UIScrollView.initializeParade()

Create Animatable View

The first step is to make a view animatable by implement the PDAnimatableType protocol, and the scrollview will begin to communicate progress to it's subviews accordingly.

public protocol PDAnimatableType {

    // The progress animator definition that
    // interpolates over animatable properties
    func configuredAnimator() -> PDAnimator;
}

Any of the following views, and their subviews, can implement the PDAnimatableType and be animated:

  • UICollectionViewCell
  • UITableViewCell
  • UIScrollView's subviews

But before the scrollview can communicate the progress, define an animator with the relative scroll direction that the scrollview will be tracking against. Bundled with the framework is recursive blocks based builder, that allows for simple creation of complex animations to interpolate against while scrolling.

Vertical Direction Scroll Animator

The following is an example to create a vertical animator for scrolling vertically. The closure returns an animator that can be used to create from, and to, state for any specific view within the hierarchy.

func configuredAnimator() -> PDAnimator {

   /* Create a vertical tracking animator call this class method */
   return PDAnimator.newVerticalAnimator { (animator) in

   }
}

Horizontal Direction Scroll Animator

The following is an example to create a horizontal animator for scrolling horizontally. The closure returns an animator that can be used to create from, and to, state for any specific view within the hierarchy.

func configuredAnimator() -> PDAnimator {

   /* Create a horizontal tracking animator with this class method */
   return PDAnimator.newHorizontalAnimator { (animator) in

   }
}

The closure returns an animator that can be used to create from, and to, states for a specific view accordingly.

Configuring Animation States

Configure End State

To have a view fade in relative to the scrolling progress, define a start state by calling the startState(for:) method as follows. Each time a state is added, it returns a state maker that can be used to append multiple properties to interpolate over.

func configuredAnimator() -> PDAnimator {

    let offScreenAlpha : CGFloat = 0.0

    return PDAnimator.newVerticalAnimator { (animator) in

        animator.startState(for: animatedImageView, { (s) in
          s.alpha(offScreenAlpha)
        })
     }
}

Configure End State

Building on the last example, to have a view fade out relative to the scrolling progress off the screen, define an end state by calling the endState(for:) method as follows.

func configuredAnimator() -> PDAnimator {

    let offScreenAlpha : CGFloat = 0.0

    return PDAnimator.newVerticalAnimator { (animator) in

        animator.startState(for: animatedImageView, { (s) in
          s.alpha(offScreenAlpha)
        }).endState(for: animatedImageView, { (s) in
          s.alpha(offScreenAlpha)
        })
     }
}

Configure Start & End State

Building on the prior example, it appears that the appearing and disappearing alpha is the same. In the case both start, and end state values are the same, use the startEndState(for:) method to set the value for both states simultaneously.

func configuredAnimator() -> PDAnimator {

    let offScreenAlpha : CGFloat = 0.0

    return PDAnimator.newVerticalAnimator { (animator) in

        animator.startEndState(for: animatedImageView, { (s) in
          s.alpha(offScreenAlpha)
        })
     }
}

Start & End State for Multiple Views

In the case there are multiple views that need to perform the same animation, helper methods have been defined for creating animations for an array of views too. The following is an example of how these can be used.

func configuredAnimator() -> PDAnimator {

    var animatedViews = [view1, view2, view3, view4]

    let offScreenAlpha : CGFloat = 0.0

    return PDAnimator.newVerticalAnimator { (animator) in

        animator.startEndState(forViews: animatedViews, { (s) in
          s.alpha(offScreenAlpha)
        })
     }
}

The following can also be used with multiple views.

func startState(forViews views:  [UIView], _ callback : ... )    -> PDAnimationMaker
func endState(forViews views:  [UIView], _ callback : ... )      -> PDAnimationMaker
func startEndState(forViews views:  [UIView], _ callback : ... ) -> PDAnimationMaker

State Properties

The framework provides quite a few helpers to define state properties for views, and/or, their backing layer with ease.

/* View Property Setters */

public func alpha(_ value : CGFloat)               -> PDAnimatablePropertyMaker
public func backgroundColor(_ value : UIColor)     -> PDAnimatablePropertyMaker
public func bounds(_ value : CGSize)               -> PDAnimatablePropertyMaker
public func center(_ value : CGPoint)              -> PDAnimatablePropertyMaker
public func size(_ value : CGSize)                 -> PDAnimatablePropertyMaker
public func transform(_ value : CGAffineTransform) -> PDAnimatablePropertyMaker

/* Layer Property Setters */

public func borderColor(_ value : UIColor)         -> PDAnimatablePropertyMaker
public func borderWidth(_ value : CGFloat)         -> PDAnimatablePropertyMaker
public func contentsRect(_ value : CGRect)         -> PDAnimatablePropertyMaker
public func cornerRadius(_ value : CGFloat)        -> PDAnimatablePropertyMaker
public func shadowColor(_ value : UIColor)         -> PDAnimatablePropertyMaker
public func shadowOffset(_ value : CGSize)         -> PDAnimatablePropertyMaker
public func shadowOpacity(_ value : CGFloat)       -> PDAnimatablePropertyMaker
public func shadowRadius(_ value : CGFloat)        -> PDAnimatablePropertyMaker
public func transform3D(_ value : CATransform3D)   -> PDAnimatablePropertyMaker
public func zPosition(_ value : CGFloat)           -> PDAnimatablePropertyMaker

In the case a setter is not defined, and there is a need to set a specific property to interpolate between, there are two defined setters that use KVC for views, and/or, their backing layer accordingly.

public func viewValue(_ value : Any?, forKey key : String)    -> PDAnimatablePropertyMaker
public func layerValue(_ value : Any?, forKey key : String)   -> PDAnimatablePropertyMaker

Parametric Easing

There are 46 different parametric curves that can be applied to the interpolation of uniquely per property. The framework comes bundled with the following supported parametric curves that can be applied to each property individually.

.inSine
.inOutSine
.outSine
.outInSine
.inQuadratic
.inOutQuadratic
.outQuadratic
.outInQuadratic
.inCubic
.inOutCubic
.outCubic
.outInCubic
.inQuartic
.inOutQuartic
.outQuartic
.outInQuartic
.inQuintic
.inOutQuintic
.outQuintic
.outInQuintic
.inAtan
.inOutAtan
.outAtan
*
.inExponential
.inOutExponential
.outExponential
.outInExponential
.inCircular
.inOutCircular
.outCircular
.outInCircular
.inBack
.inOutBack
.outBack
.outInBack
.inElastic
.inOutElastic
.outElastic
.outInElastic
.inBounce
.inOutBounce
.outBounce
.outInBounce
.linear
.smoothStep
.smootherStep
*

Just append it to the state's property definition while building the view's state. A good reference for some of the supported parametric curves can be found here

func configuredAnimator() -> PDAnimator {

    let offScreenAlpha : CGFloat = 0.0
    let offScreenTransform = CGAffineTransform.identity.scaledBy(x: 0.5, y: 0.5)

    return PDAnimator.newVerticalAnimator { (animator) in

        animator.startEndState(for: animatedImageView, { (s) in
          s.alpha(offScreenAlpha).easing.(.inSine)
          s.transform(offScreenTransform).easing(.inOutCubic)
        })
     }
}

Advanced View Animations

Chaining Animations

Animation progress does not have to apply only to the top level view that is being scrolled. If a subview implements the PDAnimatableType, and is part of the subview hierarchy, attaching it to the animator can create a chain.

The animator will then communicate the progress to the subview's animator, subviews can be attached to subviews, or even have the subviews attach to their subviews, to create chains that can traverse multiple levels in the end to make some fun effects. To attach an animatable view, call the attachAnimatableView(:) method as follows.

func configuredAnimator() -> PDAnimator {

    let offScreenAlpha : CGFloat = 0.0
    let offScreenTransform = CGAffineTransform.identity.translatedBy(x: 0.0, y: 100.0)

    return PDAnimator.newVerticalAnimator { (animator) in

        animator.startEndState(for: animatedImageView, { (s) in
          s.transform(offScreenTransform).easing(.inOutCubic)
        }).attachAnimatableView(animatedImageView)
     }
}

Bounding Progress Range

There is sometimes a need to adjust where the progress actually takes place. This is especially useful when animatable view is smaller than the bounding size of the scrollview. Observe the examples of the ranges defined, and how it effects the progress. By defining a range, this is basically telling the scrollview where the progress counts from 0 to 100.

alt tag

Ranges can be defined on a per property basis just like easing – thus allowing for different properties interpolating over different coordinate spaces. The following example defines two different ranges for each property, and can visually be referenced above as to where the interpolation will take place.

func configuredAnimator() -> PDAnimator {

    let offScreenAlpha : CGFloat = 0.0
    let offScreenTransform = CGAffineTransform.identity.translatedBy(x: 0.0, y: 100.0)

    return PDAnimator.newVerticalAnimator { (animator) in

        animator.startState(for: animatedImageView, { (s) in
          s.transform(offScreenTransform).easing(.inOutCubic).range(0.5...1.0)
          s.alpha(offScreenTransform).easing(.inOutCubic).range(0.25...0.75)
        })
     }
}

License

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

You might also like...
Beautiful iOS side menu library with parallax effect. Written in Swift
Beautiful iOS side menu library with parallax effect. Written in Swift

AKSideMenu AKSideMenu is a double side menu library with parallax effect. Example Project See the contained examples to get a sample of how AKSideMenu

Recreating the cool parallax icons from Apple TV as iOS UIButtons (in Swift).
Recreating the cool parallax icons from Apple TV as iOS UIButtons (in Swift).

TVButton Recreating the cool parallax icons from Apple TV as iOS UIButtons (in Swift). The effect is triggered by long pressing or dragging. Usage Imp

UICollectionView replacement of UITableView. Do even more like Parallax Header, Sticky Section Header. Made for iOS 7.

CSStickyHeaderFlowLayout Contributors For anyone who'd like to be a contributor to the repository, please read the Contribution Guideline Parallax, St

Apple TV Parallax effect in Swift.
Apple TV Parallax effect in Swift.

MPParallaxView Apple TV Parallax effect in Swift. Rotate view using touch or accelerometer. Usage To run the example project, clone the repo, and run

Simple parallax header for UIScrollView
Simple parallax header for UIScrollView

MXParallaxHeader ⚠️ This project is no longer maintained, see #124 ⚠️ MXParallaxHeader is a simple header class for UIScrollView. In addition, MXScrol

HPParallaxHeader is a simple parallax header class for UIScrollView.
HPParallaxHeader is a simple parallax header class for UIScrollView.

HPParallaxHeader is a simple parallax header class for UIScrollView.

ScrollView that supports a parallax header image and static overlay.

ScrollViewReactiveHeader A replacement ScrollView that provides a header with subtle scroll animations. example-video.mov Using ScrollViewReactiveHead

A SwiftUI ScrollView Designed to imitate the App Store and Apple Music ScrollViews (with or without a Parallax Header)
A SwiftUI ScrollView Designed to imitate the App Store and Apple Music ScrollViews (with or without a Parallax Header)

FancyScrollView I spent a lot of time looking for a way to recreate the UI of the ScrollViews in Stock Apple Apps (i.e. App Store and Apple Music) ins

A lightweight 3D Linear Carousel with parallax effect
A lightweight 3D Linear Carousel with parallax effect

TGLParallaxCarousel A lightweight 3D Linear Carousel with parallax effect [GIF] Threedimensional & Normal mode Installation TGLParallaxCarousel is ava

Parallax scrolling effect on UITableView header view when a tableView is scrolled
Parallax scrolling effect on UITableView header view when a tableView is scrolled

ParallaxTableViewHeader Parallax scrolling effect on UITableView header view when a tableView is scrolled Usage Create a ParallaxHeaderView using eith

✨ Super easy Parallax and Haptic Effect.
✨ Super easy Parallax and Haptic Effect.

IParallaxAndHapticEffect ✨ Super easy Parallax and Haptic Effect. This library helps you easily use the 'Parallax' and 'Haptic' effects. Customized 3D

Simple way to add parallax header to UIScrollView/UITableView written in Swift.
Simple way to add parallax header to UIScrollView/UITableView written in Swift.

ParallaxHeader Simple way to add parallax header to UIScrollView or it's subclasses. One image view Slider with images Blur vibrant text Blur round ic

A tiny category on UIView that allows you to set one property:
A tiny category on UIView that allows you to set one property: "parallaxIntensity" to achieve a parallax effect with UIMotionEffect

NGAParallaxMotion A tiny category on UIView that allows you to set one property: parallaxIntensity to achieve a parallax effect with UIMotionEffect. S

An iOS library to natively render After Effects vector animations
An iOS library to natively render After Effects vector animations

Lottie for iOS, macOS (and Android and React Native) View documentation, FAQ, help, examples, and more at airbnb.io/lottie Lottie is a mobile library

Kanvas is an open-source iOS library for adding effects, drawings, text, stickers, and making GIFs from existing media or the camera.
Kanvas is an open-source iOS library for adding effects, drawings, text, stickers, and making GIFs from existing media or the camera.

Kanvas Kanvas is an open-source iOS library for adding effects, drawings, text, stickers, and making GIFs from existing media or the camera.

SwiftUI Animation Library. Useful SwiftUI animations including Loading/progress, Looping, On-off, Enter, Exit, Fade, Spin and Background animations that you can directly implement in your next iOS application or project. The library also contains huge examples of spring animations such as Inertial Bounce, Shake, Twirl, Jelly, Jiggle, Rubber Band, Kitchen Sink and Wobble effects. Browse, find and download the animation that fits your needs.  iOS multi-functional AI camera: portrait cartoon, ageing and rejuvenation, beauty, filters, artistic effects, etc.
iOS multi-functional AI camera: portrait cartoon, ageing and rejuvenation, beauty, filters, artistic effects, etc.

Magic Camera is an iOS AI camera app based on SwiftUI and CoreML that implements the following features: Portrait Cartoonization, which turns your photos into cartoon avatars Portrait Style Migration, which makes your photos older, younger, hair color, etc Beauty Camera, which supports peeling

A beautiful activity indicator and modal alert written in Swift (originally developed for my app DoodleDoodle) Using blur effects, translucency, flat and bold design - all iOS 8 latest and greatest
A beautiful activity indicator and modal alert written in Swift (originally developed for my app DoodleDoodle) Using blur effects, translucency, flat and bold design - all iOS 8 latest and greatest

SwiftSpinner SwiftSpinner is an extra beautiful activity indicator with plain and bold style. It uses dynamic blur and translucency to overlay the cur

Various view's effects for iOS, written in Swift. Allows you to animate views nicely with easy to use extensions
Various view's effects for iOS, written in Swift. Allows you to animate views nicely with easy to use extensions

Various view's effects for iOS, written in Swift. Allows you to animate views nicely with easy to use extensions. Every animation is randomized. Currently supported animations:

Comments
  • How refresh animation setting

    How refresh animation setting

    When I adjust the animation for a dynamically changeable height cell image, then when I reuse this cell, I need to update the animation setting. How can i do this?

    opened by Vladlen1 0
  • Question About Resetting The PDAnimator

    Question About Resetting The PDAnimator

    Hi, Great library! I have a question regarding the PDAnimator. Is it possible to reset this or remove it from the element e.g. a UICollectionViewCell after it has been initialised?

    opened by ghost 0
Owner
Elephant
We are a human experience design company based in San Francisco, New York, Los Angeles, and London.
Elephant
Reusable iOS's behavior drag or swipe to pop ViewController

DLSwipeToPopController Reusable iOS's behavior to pop ViewController base on SwipeRightToPopController: Swipe from Right to Left to pop ViewController

Le Ngoc Duy 1 Sep 17, 2022
An iOS drop-in UITableView, UICollectionView and UIScrollView superclass category for showing a customizable floating button on top of it.

MEVFloatingButton An iOS drop-in UITableView, UICollectionView, UIScrollView superclass category for showing a customizable floating button on top of

Manuel Escrig 298 Jul 17, 2022
Easy and type-safe iOS table and collection views in Swift.

Quick Start TL;DR? SimpleSource is a library that lets you populate and update table views and collection views with ease. It gives you fully typed cl

Squarespace 96 Dec 26, 2022
It's simple IOS Study Case - Movie App

IOS Deployment Info: IOS 15.0 ve üzeri Kullanılan Teknolojiler ve Yapılar Kingfisher AVFoundation URLSession Generics CollectionView VIPER Swipe Gestu

Bilge Çakar 4 Jul 31, 2022
A scroll view with a sticky header which shrinks as you scroll. Written with SwiftUI.

Scaling Header Scroll View A scroll view with a sticky header which shrinks as you scroll. Written with SwiftUI. We are a development agency building

Exyte 395 Dec 31, 2022
tvOS controls and extensions that add parallax effect to your application.

ParallaxView Summary Easy to use UIView, UICollectionViewCell with parallax effect and extensions to add this effect to any UIView. Rotate view using

PGS Software 466 Nov 13, 2022
Imagine Engine - a fast, high performance Swift 2D game engine for Apple's platforms

Welcome to Imagine Engine, an ongoing project that aims to create a fast, high performance Swift 2D game engine for Apple's platforms that is also a j

John Sundell 1.8k Jan 3, 2023
Palico Engine: Metal-Based Game Engine in Swift 🐑

Palico Engine: Metal-Based Game Engine in Swift ?? Implement a game engine on macOS using Metal API. Still in development. Currently I am working on a

Junhao Wang 24 Dec 1, 2022
2D ECS game engine in 100% Swift + SwiftUI for iOS, macOS, tvOS

OctopusKit A 2D game engine based on ECS and written in 100% Swift for iOS, macOS and tvOS. If you've tried making a game in Swift while sticking to t

null 335 Dec 12, 2022
iOS 7/8 style side menu with parallax effect.

RESideMenu iOS 7/8 style side menu with parallax effect inspired by Dribbble shots (first and second). Since version 4.0 you can add menu view control

Roman Efimov 7.2k Dec 28, 2022