Gemini is rich scroll based animation framework for iOS, written in Swift.

Last update: May 18, 2022

Overview

What is the Gemini?

Gemini is rich scroll based animation framework for iOS, written in Swift. You can easily use GeminiCollectionView, which is a subclass of UICollectionView.

It enables you to make multiple animation which has various and customizable properties, and moreover can create your own custom scroll animation.

Gemini also provides a fluent interface based on method chaining. you can use this intuitively and simply.

collectionView.gemini
    .circleRotationAnimation()
    .radius(400)
    .rotateDirection(.clockwise)

Features

Platform Cocoapods Carthage compatible License Swift pod

  • Rich animation with scrolling
  • Easily usable
  • Highly customizable
  • Several types of animations and properties
  • Supports vertical and horizontal flow layout
  • Supports easing function
  • Supports Swift5.0
  • Fluent interfaces based on method chaining
  • Compatible with Carthage
  • Compatible with CocoaPods
  • Example project with lots of stock animations
  • And More...

Contents

Animation Types and properties

The following animation types are available. See sample code here for details.

In addition, you can also customize the following properties for the above animation types.

Cube

It's a cube animation like Instagram. If you would like to customize the cube animation, change cubeDegree. If cubeDegree is 90, it moves like a regular hexahedron.

collectionView.gemini
    .cubeAnimation()
    .cubeDegree(90)

CircleRotation

An animation moves in a circle. You can change circleRadius and CircleRotationDirection.

collectionView.gemini
    .circleRotationAnimation()
    .radius(450) // The radius of the circle
    .rotateDirection(.clockwise) // Direction of rotation. 
    .itemRotationEnabled(true) // Whether the item rotates or not.

3D vector rotation

Available for Roll, Pitch and Yaw animation. These rotation animation are designed based on 3-Dimensional vector. Figure-1 shows direction of rotation based on device.

Figure-1 Pitch, roll, and yaw axes

Reference: Event Handling Guide for UIKit Apps

Roll Rotation

Pitch Rotation

Yaw Rotation

Each types of rotation animation has RotationEffect(e.g. RollRotationEffect) and degree of rotation.

Customize RotationEffect (up, down, sineWave, reverseSineWave) and degree of rotation.

In the case of rollRotation, like this:

collectionView.gemini
    .rollRotationAnimation()
    .degree(45)
    .rollEffect(.rollUp)

Scale

The scaleUp gradually increases frame size, scaleDown decreases.

collectionView.gemini
    .scaleAnimation()
    .scale(0.75)
    .scaleEffect(.scaleUp) // or .scaleDown

Custom

You can flexibly and easily customize scroll animation. Customize properties of GeminiAnimation.custom such as scale, scaleEffect, rotationAngle, translation, easing, shadowEffect, alpha, cornerRadius, backgroundColor, anchorPoint, etc.

The animation of gif is customized in the following way:

collectionView.gemini
    .customAnimation()
    .translation(y: 50)
    .rotationAngle(y: 13)
    .ease(.easeOutExpo)
    .shadowEffect(.fadeIn)
    .maxShadowAlpha(0.3)

Or right side of gifs is customized as follows:

collectionView.gemini
    .customAnimation()
    .backgroundColor(startColor: lightGreenColor, endColor: lightBlueColor)
    .ease(.easeOutSine)
    .cornerRadius(75)

There are more sample code at CustomAnimationViewController.swift.

Easing function

Gemini supports various easing functions based on distance of scroll.

  • linear
  • easeInQuad
  • easeOutQuad
  • easeInOutQuad
  • easeInCubic
  • easeOutCubic
  • easeInOutCubic
  • easeInQuart
  • easeOutQuart
  • easeInOutQuart
  • easeInQuint
  • easeOutQuint
  • easeInOutQuint
  • easeInSine
  • easeOutSine
  • easeInOutSine
  • easeInExpo
  • easeOutExpo
  • easeInOutExpo
  • easeInCirc
  • easeOutCirc
  • easeInOutCirc

Shadow effect

Default value is ShadowEffect.none. Return shadowView in your custom class, which is a subclass of GeminiCell.

  • fadeIn
  • nextFadeIn
  • previousFadeIn
  • fadeOut
  • none
class CustomCollectionViewCell: GeminiCell {
    @IBOutlet weak var customShadowView: UIView!
    override var shadowView: UIView? {
        return customShadowView
    }
}

Usage

  1. Use Gemini classes

Gemini is designed to be easy to use. Use GeminiCollectionView and GeminiCell. These classes is subclass of UICollectionView, UICollectionViewCell.

  1. Configure animation

Configure animation with fluent interface based on method chaining. You can develop expressive code that enhances readability.

  1. Call function for animation

Finally, call animateVisibleCells() in scrollViewDidScroll(_:)

NOTE: If you want to adapt animation immediately after view is displayed, call animateCell(_:) in collectionView(_:cellForItemAt:) and collectionView(_:willDisplay:forItemAt:).

// Import Gemini
import Gemini

// Inherite GeminiCell
class CustomCell: GeminiCell {
    ...
}

// Conform to UICollectionViewDelegate and UICollectionViewDataSource
class CustomViewController: UIViewController: UICollectionViewDelegate, UICollectionViewDataSource {

    // Inherite GeminiCollectionView
    @IBOutlet weak var collectionView: GeminiCollectionView!

    ...

    // Configure animation and properties
    func configureAnimation() {
        collectionView.gemini
            .circleRotationAnimation()
            .radius(400)
            .rotateDirection(.clockwise)
    }

    // Call animation function
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        collectionView.animateVisibleCells()
    }

    func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
        if let cell = cell as? GeminiCell {
            self.collectionView.animateCell(cell)
        }
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CustomCell", for: indexPath) as! CustomCell
        self.collectionView.animateCell(cell)
        return cell
    }

See Example, for more details.

To run the example project, clone the repo, and run pod install from the Example directory first.

Requirements

  • Xcode 10.2.1
  • Swift 5.0

Installation

CocoaPods

Gemini is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod "Gemini"

Carthage

Add the following line to your Cartfile:

github "shoheiyokoyama/Gemini"

Author

Shohei Yokoyama

License

Gemini is available under the MIT license. See the LICENSE file for more info.

GitHub

https://github.com/shoheiyokoyama/Gemini
Comments
  • 1. Expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions

    fyi: failing to compile in Swift 4 https://github.com/shoheiyokoyama/Gemini/blob/16529b218dffd7d4e13d20e4e9fc6a2c50c233d1/Gemini/GeminiAnimationModel.swift#L191

    Reviewed by steve21124 at 2017-08-11 18:23
  • 2. Value of type '[UICollectionViewCell]' has no member 'compactMap'

    The newest version get error in the method below.

    visibleCellsValue of type '[UICollectionViewCell]' has no member 'compactMap'

    // Call this method in `scrollViewDidScroll(_:)`.
        public func animateVisibleCells() {
            guard let model = animationModel, model.isEnabled else { return }
    
            visibleCells
                .compactMap { $0 as? GeminiCell }
                .forEach { [weak self] cell in
                    self?.animateCell(cell)
                }
        }
    
    Reviewed by Benyi-Peng at 2018-06-08 01:54
  • 3. could not install pod in Xcode 9.3

    pod init

    ――― MARKDOWN TEMPLATE ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――

    Command

    /usr/local/bin/pod init
    

    Report

    • What did you do?

    • What did you expect to happen?

    • What happened instead?

    Stack

       CocoaPods : 1.3.1
            Ruby : ruby 2.3.3p222 (2016-11-21 revision 56859) [universal.x86_64-darwin17]
        RubyGems : 2.5.2
            Host : Mac OS X 10.13.4 (17E202)
           Xcode : 9.3 (9E145)
             Git : git version 2.15.1 (Apple Git-101)
    Ruby lib dir : /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib
    Repositories : master - https://github.com/CocoaPods/Specs.git @ 08efba4093074e5433f487070b5fbcbfb9fb5f6f
    

    Plugins

    cocoapods-deintegrate : 1.0.1
    cocoapods-plugins     : 1.0.0
    cocoapods-search      : 1.0.0
    cocoapods-stats       : 1.0.0
    cocoapods-trunk       : 1.3.0
    cocoapods-try         : 1.1.0
    

    Error

    RuntimeError - [Xcodeproj] Unknown object version.
    /Library/Ruby/Gems/2.3.0/gems/xcodeproj-1.5.4/lib/xcodeproj/project.rb:217:in `initialize_from_file'
    /Library/Ruby/Gems/2.3.0/gems/xcodeproj-1.5.4/lib/xcodeproj/project.rb:102:in `open'
    /Library/Ruby/Gems/2.3.0/gems/cocoapods-1.3.1/lib/cocoapods/command/init.rb:41:in `validate!'
    /Library/Ruby/Gems/2.3.0/gems/claide-1.0.2/lib/claide/command.rb:333:in `run'
    /Library/Ruby/Gems/2.3.0/gems/cocoapods-1.3.1/lib/cocoapods/command.rb:52:in `run'
    /Library/Ruby/Gems/2.3.0/gems/cocoapods-1.3.1/bin/pod:55:in `<top (required)>'
    /usr/local/bin/pod:22:in `load'
    /usr/local/bin/pod:22:in `<main>'
    

    ――― TEMPLATE END ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――

    [!] Oh no, an error occurred.

    Search for existing GitHub issues similar to yours: https://github.com/CocoaPods/CocoaPods/search?q=%5BXcodeproj%5D+Unknown+object+version.&type=Issues

    If none exists, create a ticket, with the template displayed above, on: https://github.com/CocoaPods/CocoaPods/issues/new

    Be sure to first read the contributing guide for details on how to properly submit a ticket: https://github.com/CocoaPods/CocoaPods/blob/master/CONTRIBUTING.md

    Don't forget to anonymize any private data!

    Looking for related issues on cocoapods/cocoapods...

    • RuntimeError - [Xcodeproj] Unknown object version. 🌈 https://github.com/CocoaPods/CocoaPods/issues/7712 [closed] [9 comments] a week ago

    • RuntimeError - [Xcodeproj] Unknown object version. https://github.com/CocoaPods/CocoaPods/issues/7697 [closed] [12 comments] a day ago

    • RuntimeError - [Xcodeproj] Unknown object version. https://github.com/CocoaPods/CocoaPods/issues/7458 [closed] [12 comments] 5 weeks ago

    and 37 more at: https://github.com/cocoapods/cocoapods/search?q=[Xcodeproj]%20Unknown%20object%20version.&type=Issues&utf8=✓

    Reviewed by AgaramDevelopment at 2018-05-15 13:40
  • 4. CollectionView didSelectItemAt not being called

    Hello,

    I've created a pull request here which shows a problem where didSelectItemAt in UICollectionViewDelegate is not being called when I use Gemini.

    Here is the link:

    https://github.com/shoheiyokoyama/Gemini/pull/2

    Does anyone else have this problem or knows how to work around this?

    Thank you.

    Reviewed by agarbowitzOmadaHealth at 2017-08-09 22:36
  • 5. Collection view delegate didSelectAt is never getting called

    I'm trying to call code when a cell is tapped, but the didSelectAt method never gets called. This example illustrates the problem within the sample project.

    Can someone please help?

    Thanks.

    Reviewed by agarbowitzOmadaHealth at 2017-08-09 22:35
  • 6. Invisible view on top of horizontal scale animation

    Is there anyway to remove this view on top of horizontal scale animation. I have added a button into the card views but I cannot access it because of the view on top.

    Reviewed by Abstract45 at 2018-06-07 19:24
  • 7. Bump cocoapods-downloader from 1.2.2 to 1.6.3

    Bumps cocoapods-downloader from 1.2.2 to 1.6.3.

    Release notes

    Sourced from cocoapods-downloader's releases.

    1.6.3

    Enhancements
    • None.
    Bug Fixes
    • None.

    1.6.2

    Enhancements
    • None.
    Bug Fixes
    • None.

    1.6.1

    Enhancements
    • None.
    Bug Fixes
    • None.

    1.6.0

    Enhancements
    • None.
    Bug Fixes
    • Adds a check for command injections in the input for hg and git.
      orta #124

    1.5.1

    Enhancements
    • None.
    Bug Fixes
    • Fix "can't modify frozen string" errors when pods are integrated using the branch option
      buju77 #10920

    1.5.0

    ... (truncated)

    Changelog

    Sourced from cocoapods-downloader's changelog.

    1.6.3 (2022-04-01)

    Enhancements
    • None.
    Bug Fixes
    • None.

    1.6.2 (2022-03-28)

    Enhancements
    • None.
    Bug Fixes
    • None.

    1.6.1 (2022-03-23)

    Enhancements
    • None.
    Bug Fixes
    • None.

    1.6.0 (2022-03-22)

    Enhancements
    • None.
    Bug Fixes
    • Adds a check for command injections in the input for hg and git.
      orta #124

    1.5.1 (2021-09-07)

    Enhancements
    • None.

    ... (truncated)

    Commits
    • c03e2ed Release 1.6.3
    • f75bccc Disable Bazaar tests due to macOS 12.3 not including python2
    • 52a0d54 Merge pull request #128 from CocoaPods/validate_before_dl
    • d27c983 Ensure that the git pre-processor doesn't accidentally bail also
    • 3adfe1f [CHANGELOG] Add empty Master section
    • 591167a Release 1.6.2
    • d2564c3 Merge pull request #127 from CocoaPods/validate_before_dl
    • 99fec61 Switches where we check for invalid input, to move it inside the download fun...
    • 96679f2 [CHANGELOG] Add empty Master section
    • 3a7c54b Release 1.6.1
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    Reviewed by dependabot[bot] at 2022-04-05 22:22
  • 8. CompositionalLayout - Feature Request

    Hi,

    Gemini seems to be not working when using a UICollectionViewDiffableDataSource along with a UICollectionViewCompositionalLayout.

    The scrolling function func scrollViewDidScroll(_ scrollView: UIScrollView) is not called on scroll in these layouts by design, rather:

    section.orthogonalScrollingBehavior = .groupPagingCentered
    section.visibleItemsInvalidationHandler = { visibleItems, scrollOffset, layoutEnvironment in
                     self.collectionView.animateVisibleCells()  
    }
    

    is used to detect scrolling for each section, but calling the animation function seems to only do the animation once initially.

    I'm also calling the animation in

    func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    
            guard let customCell = cell as? MyCollectionCell else { return }
            self.collectionView.animateCell(customCell)
    }
    

    and its set as

    collectionView.gemini.customAnimation().translation(x: 0, y: 50, z: 0).rotationAngle(x: 0, y: 13, z: 0).ease(.easeOutExpo)
    
    Reviewed by egenvall at 2020-04-27 07:31
  • 9. dyld: Library not loaded: @rpath/Gemini.framework/Gemini

    Installed gemini via Carthage and got this error at runtime. "dyld: Library not loaded: @rpath/Gemini.framework/Gemini".

    I cannot add the framework using repo url as well. " Got this error below. Showing All Messages : https://github.com/shoheiyokoyama/Gemini.git has no Package.swift manifest for version 1.4.0

    Reviewed by panncherry at 2019-12-20 20:11
  • 10. Swift 5 warnings fixes

    Handle Switch Swift 5 Warnings (Added @unknown default) Fixed Example CustomAnimationViewController (added default values in translation and rotationAngle)

    Reviewed by alexookah at 2019-11-21 19:52
Apr 27, 2022
Simple Interface Core Animation. Run type-safe animation sequencially or parallelly
Simple Interface Core Animation. Run type-safe animation sequencially or parallelly

Simple Interface Core Animation Sica can execute various animations sequentially or parallelly. Features Animation with duration and delay parallel /

Apr 28, 2022
An experiment for using SwiftUI's custom timing Animation to create an orbital-like animation.
An experiment for using SwiftUI's custom timing Animation to create an orbital-like animation.

Orbital-SwiftUI-Animation An experiment for using SwiftUI's custom timing curve to create an orbital-like animation. How it looks: How it works: Apply

Apr 3, 2022
SwiftUI-Text-Animation-Library - Text animation library for SwiftUI
SwiftUI-Text-Animation-Library - Text animation library for SwiftUI

⚠️ This repository is under construction. SwiftUI Text Animation Library Make yo

May 10, 2022
Swiftui-animation-observer - Track SwiftUI animation progress and completion via callbacks
Swiftui-animation-observer - Track SwiftUI animation progress and completion via callbacks

SwiftUI Animation Observer Track SwiftUI animation progress and completion via c

May 6, 2022
An extensible iOS and OS X animation library, useful for physics-based interactions.
An extensible iOS and OS X animation library, useful for physics-based interactions.

Pop is an extensible animation engine for iOS, tvOS, and OS X. In addition to basic static animations, it supports spring and decay dynamic animations

May 17, 2022
YapAnimator is your fast and friendly physics-based animation system
YapAnimator is your fast and friendly physics-based animation system

YapAnimator is your fast and friendly physics-based animation system. YapAnimator was built with ease-of-use in mind, keeping you sane and your design

Apr 12, 2022
Anima is chainable Layer-Based Animation library for Swift5.
Anima is chainable Layer-Based Animation library for Swift5.

Anima Anima is chainable Layer-Based Animation library for Swift5. It support to make sequensial and grouped animation more easily. is written as foll

Feb 28, 2022
Pulse animation for iOS written with Swift.
Pulse animation for iOS written with Swift.

Pulsator Pulse animation for iOS written with Swift. Great For: Pulses of Bluetooth, BLE, beacons (iBeacon), etc. Map Annotations Installation CocoaPo

May 14, 2022
A DSL to make animation easy on iOS with Swift.
A DSL to make animation easy on iOS with Swift.

This project is highly inspired by JHChainableAnimations, If you project is developed with Objective-C, use JHChainableAnimations instead. With DKChai

Apr 18, 2022
Swift animation library for iOS, tvOS and macOS.
Swift animation library for iOS, tvOS and macOS.

anim is an animation library written in Swift with a simple, declarative API in mind. // moves box to 100,100 with default settings anim { self.bo

Apr 28, 2022
Animation library for iOS in Swift
Animation library for iOS in Swift

TweenKit TweenKit is a powerful animation library that allows you to animate (or 'tween') anything. TweenKit's animations are also scrubbable, perfect

May 17, 2022
Easy animation library on iOS with Swift2
Easy animation library on iOS with Swift2

Cheetah Cheetah is an animation utility on iOS with Swift. Cheetah can animate any properties since Cheetah uses simple CADisplayLink run loop to chan

Apr 25, 2022
A radical & elegant animation library for iOS.
A radical & elegant animation library for iOS.

Installation • Usage • Debugging • Animatable Properties • License Dance is a powerful and straightforward animation framework built upon the new UIVi

Apr 12, 2022
Pulse animation for iOS

Pulsator Pulse animation for iOS written with Swift. Great For: Pulses of Bluetooth, BLE, beacons (iBeacon), etc. Map Annotations Installation CocoaPo

Jun 19, 2021
iOS Component for creating a pulsing animation.

PulsingHalo PulsingHalo has been discontinued, and is no longer being maintained. Please check out Pulsator which is the new version of this written w

May 12, 2022
Widgets iOS 14 animation with 3D and dynamic shadow. Customisable transform and duration.
Widgets iOS 14 animation with 3D and dynamic shadow. Customisable transform and duration.

SPPerspective About Animatable widgets from iOS 14. Same animation for transform and shadow. Customisable duration, perspective and shadow also. For v

May 11, 2022
This library is for adding animation to iOS tabbar items, which is inherited from UITabBarController.
This library is for adding animation to iOS tabbar items, which is inherited from UITabBarController.

This library is for adding animation to iOS tabbar items, which is inherited from UITabBarController. Installation Just add the Sources folder to your

May 7, 2022