Git Product home page Git Product logo

ubergang's Introduction

Ubergang - a tweening engine for iOS

Platform iOS CocoaPods Compatible License Apache2 iOS

Ubergang is a tweening engine for iOS written in Swift.

Features

  • Tween numeric values, UIColors and CGAffineTransforms
  • Tween along UIBezierPaths
  • Tween through points
  • Linear, Expo, Cubic, Quad, Circ, Quart, Quint, Sine, Back, Bounce and Elastic easings
  • Generic tween setup
  • Repeat and Yoyo tween options
  • Memory management for strong and weak tween object references
  • Tween Timelines
  • Bezier tween align to path
  • Logging and log levels

Previews

Example - Timeline Example - Timeline

Installation

    platform :ios, '8.0'
    use_frameworks!
    pod 'Ubergang'

Setup

    UTweenSetup.instance.enableLogging(true)
    UTweenSetup.instance.enableLogging(true, withLogger: loggerProxy)

Ubergang provides some logs for basic operations like start, stop, pause, ... There is a dependency to XCGLogger which is used by default, but you can pass any Logger you prefer by creating a custom logger proxy implementing UTweenLoggable.

Tween Configuration

    .options(.repeat(n))
    .options(.yoyo)
    .options(.repeat(n), .yoyo)

Using options you can let the Tween repeat n (Int) times, let it yoyo or combine both options.

  • Repeat will restart the Tween n times where repeatCycleChange will be called with every cycle.
  • Yoyo will reverse the Tween after it reaches the end value.
    .reference(.strong)` //(default)
    .reference(.weak)

reference determines how to handle the reference count for the tween. Ubergang will increase the retain count if the option is set to .strong or won't increase it if it's set to .weak. These two rules are valid for most cases:

  • The Tween is not stored in a field variable -> .strong
  • The Tween is stored in a field variable -> .weak

Usage

Start a simple numeric Tween (Double)

    0.tween(to:10).update({ (value:Int) in print("\(value)") }).start()

This Tween goes from 0 to 10 over 0.5 by default seconds using a linear easing by default. The current value will be printed with every update.

'to' and 'from' using closures

    NumericTween(id: "doubleTween")
            .from({ [unowned self] in return self.position2.x }, to: { [unowned self] in return self.position1.x })
            .update({ value, progress in print("update: \(value), progress: \(progress) ") })
            .duration(5)
            .start()

Passing closures to 'to' and 'from' will always compute all results using the current values returned by the closures.

Start a weak numeric Tween (Int)

    var tween: NumericTween<Int>?

    func run() {
        tween = 0.tween(to: 10)
            .id("intTween")
            .duration(5)
            .update({ value in print("update: \(value)") })
            .ease(.elastic(.out))
            .reference(.weak)
            .start()
    }

This Tween with id 'intTween' goes from 0 to 10 over 5 seconds using an elastic easing. The current value will be printed with every update. .reference(.weak) will store this tween weakly, Ubergang won't increment the reference count. It's up to you to keep the Tween alive.

Start a numeric Tween repeating 5 times with yoyo

    var tween: NumericTween<Int>?

    func run() {
    
        tween = 0.tween(to: 10)
            .id("intTween")
            .duration(5)
            .update({ value in print("update: \(value)") })
            .ease(.elastic(.out))
            .reference(.weak)
            .options(.repeat(5), .yoyo)
            .start()
    }

Start a weak numeric Tween (CGAffineTransform)

    @IBOutlet var testView: UIView!
    var tween: TransformTween?

    func run() {
        //declare the target values
        var to = testView.transform
        to.ty = 200.0
    
        tween = testView.transform.tween(to: transform)
            .id("testView")
            .duration(2.5)
            .reference(.weak)
            .update({ [unowned self] value in self.testView.transform = value })
    	    .start()
    }

This Tween with id 'testView' tweens a transform over 2.5 seconds. The resulting tranform will be assigned to the testView with every update 'welf.testView.transform = value'.

Start a Timeline containing three Tweens

    var timeline: UTimeline = UTimeline(id: "timeline")

    func run() {
        timeline.options(.yoyo).reference(.weak)
        
        timeline.append(
            0.tween(to: 10).id("intTween").duration(5).update({ value, _ in print("0-10 value: \(value)") })
        )
        
        timeline.append(
            0.0.tween(to: 10.0).id("floatTween1").duration(5).update({ value, _ in print("0.0-10.0 value: \(value)") })
        )
        
        timeline.insert(
            10.0.tween(to: 0.0).id("floatTween2").duration(5).update({ value, _ in print("10.0-0.0 value: \(value)") }), at: 2.5
        )
  
        timeline.start()
    }

This Timeline controls one Tween starting at time 0.0 seconds, one Tween starting at time 5.0 seconds and the last one starting at 2.5 seconds. All Tweens are controlled by the timeline with the given options - In this case the tween option .yoyo

Tween along a UIBezierPath

    var tween: BezierPathTween!

    func run() {
    tween = BezierPathTween().along(path)
            .id("bezierTween")
            .duration(5)
            .ease(.linear)
            .reference(.weak)
            .update({ [unowned self] (value: CGPoint, progress: Double) in
                //update
            })
            .start()
    }

Tween through points

    var tween: BezierPathTween!

    func run() {
        let points = [CGPoint]()
        points.append(...)

        tween = BezierPathTween().along(points)
            .id("bezierTween")
            .duration(5)
            .ease(.linear)
            .reference(.weak)
            .update({ [unowned self] (value: CGPoint, progress: Double) in
                //update
            })
            .start()
    }    

Tween through points and use orientation to align the object on update

    var tween: BezierPathTween!

    func run() {
        let points = [CGPoint]()
        points.append(...)

        tween = BezierPathTween().along(points)
            .id("bezierTween")
            .duration(5)
            .ease(.linear)
            .reference(.weak)
            .update({ [unowned self] (value:CGPoint, progress: Double, orientation: CGPoint) in
                self.targetView.center = value

                let angle = atan2(orientation.y, orientation.x)
                let transform = CGAffineTransformRotate(CGAffineTransformIdentity, angle)
                self.targetView.transform = transform
            })
            .start()
    }      

Changelog Verion 1.2.0

  • The Ease type changed to an Enum instead of passing the function type directly e.g.
	.ease(Linear.ease) becomes .ease(.linear)
	.ease(Elastic.easeOut) becomes .ease(.elastic(.out))
  • When starting a tween which is already playing, it will now only log a warning via the logger proxy instead of guarding a restart
  • The new tween direction 'backward' will inverse easings and tween start times within a timeline
/*
    forward -->
t0: |-----------------------|
t1:     |----------------------|
t2: |--------|
*/

/*
                     <-- reverse
t0: |-----------------------|
t1:     |----------------------|
t2: |--------|
*/

/*
                    <-- backward
t0:    |-----------------------|
t1: |----------------------|
t2:                   |--------|
*/

Changelog Verion 1.1.0

  • Swift 5 migration

Changelog Verion 1.0

  • Swift 4 migration
  • Change tween creation pattern (UTweenBuilder removed - Instead instantiate the tween object directly or use the appropriate extension like 0.tween(to: 10))
  • Add @discardableResult to specific methods
  • Fix issue where timelines didn't work if there was a delay between tweens

Feedback is always appreciated

ubergang's People

Contributors

robinfalko avatar rofried avatar

Stargazers

Erekle Meskhi avatar Kevin Sie avatar  avatar Beehive Innovations avatar Dino avatar lieon avatar  avatar Andrew Kochulab avatar Alexander Lester avatar SirVon Thomas avatar Rocket avatar Cary Miller avatar Atsuya Sato avatar feelnx avatar Jimmy avatar  avatar Nam Kennic avatar ice6 avatar Felix Turner avatar Jon Hocking avatar Kai Li avatar Andritch Arthur avatar Kiran Kunigiri avatar yeswanth varma kanumuri avatar 宋立君 avatar  avatar Dinesh Raja avatar  avatar João Mourato avatar Joey Gordon avatar Diogo Antunes avatar Andrey Tyushlyaev avatar Pawan Sharma avatar Lê Khánh Tùng avatar Shams avatar  avatar Sanket avatar Jianbin LIN avatar Ajeet Pratap Maurya avatar chris avatar Gleb Karpushkin avatar linqingmo avatar Rigo avatar  avatar Noah Tran avatar stefanfessler avatar Viktor Braun avatar Evgeniy avatar 与狼共舞 avatar Lucas Farah avatar BigRiceDad avatar  avatar Gijora Dammann avatar Lyubomir Ganev avatar

Watchers

 avatar  avatar linqingmo avatar Fabio Acri avatar

ubergang's Issues

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.