{"id":2362,"url":"https://github.com/poetmountain/PMTween","last_synced_at":"2025-08-02T23:33:08.905Z","repository":{"id":16416555,"uuid":"19167658","full_name":"poetmountain/PMTween","owner":"poetmountain","description":"An elegant and flexible tweening library for iOS and tvOS.","archived":false,"fork":false,"pushed_at":"2016-07-19T23:26:48.000Z","size":849,"stargazers_count":343,"open_issues_count":0,"forks_count":21,"subscribers_count":10,"default_branch":"master","last_synced_at":"2024-11-22T05:41:46.435Z","etag":null,"topics":["animation","interpolation","motion","objective-c","tween"],"latest_commit_sha":null,"homepage":"","language":"Objective-C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/poetmountain.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-04-26T03:23:22.000Z","updated_at":"2024-06-13T09:40:03.000Z","dependencies_parsed_at":"2022-08-04T09:15:19.829Z","dependency_job_id":null,"html_url":"https://github.com/poetmountain/PMTween","commit_stats":null,"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/poetmountain%2FPMTween","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/poetmountain%2FPMTween/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/poetmountain%2FPMTween/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/poetmountain%2FPMTween/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/poetmountain","download_url":"https://codeload.github.com/poetmountain/PMTween/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228256844,"owners_count":17892647,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["animation","interpolation","motion","objective-c","tween"],"created_at":"2024-01-05T20:16:11.901Z","updated_at":"2024-12-06T17:31:00.914Z","avatar_url":"https://github.com/poetmountain.png","language":"Objective-C","funding_links":[],"categories":["UI"],"sub_categories":["Animation","Other free courses"],"readme":"PMTween is an elegant and flexible tweening library for Objective-C, currently supporting the iOS and tvOS platforms. It offers sensible default functionality that abstracts most of the hard work away, allowing you to focus on your animations and other tween tasks. But PMTween also makes it easy to dive in and modify for your own needs, whether that be custom tweening classes, supporting custom object types, or new easing equations.\n\nIf you're coding in Swift, try [MotionMachine](https://github.com/poetmountain/MotionMachine), which is based on PMTween, but with many improvements and an API tailored to that langauge.\n\n## Overview\n\n* PMTween makes both simple and complex tweening tasks easy to create.\n* Tweens can be grouped, sequenced, and nested in most any configuration you might need.\n* Includes both static and physics-based tween classes.\n* PMTween was built to easily support custom value types, easing equations, and functionality.\n* Provides notifications and blocks for many kinds of status events.\n\nAll of the base tweening classes in PMTween adopt the PMTweening protocol, and you can add any of these classes to a PMTweenGroup or PMTweenSequence instance. They can be nested as many levels deep as you'd like, and PMTweenGroup and PMTweenSequence respect the tweening properties of their children. If you want to use your own custom tween classes, simply adopt the protocol. However, PMTweenUnit offers such modularity that in most cases you can just replace the parts you need with your own implementation.\n\n**In other words, this code:**\n\n``` objc\nPMTweenEasingBlock easing = [PMTweenEasingCubic easingInOut];\nPMTweenEasingBlock easing2 = [PMTweenEasingCircular easingInOut];\n\nPMTweenUnit *tween1 = [[PMTweenUnit alloc] initWithObject:self.tweenView  propertyKeyPath:@\"frame.origin.x\" startingValue:self.tweenView.frame.origin.x endingValue:110 duration:1.5 options:PMTweenOptionNone easingBlock:easing];\nPMTweenUnit *tween2 = [[PMTweenUnit alloc] initWithObject:self.tweenView  propertyKeyPath:@\"backgroundColor.blue\" startingValue:0.30 endingValue:1.0 duration:1.2 options:PMTweenOptionNone easingBlock:easing];\nPMTweenUnit *tween3 = [[PMTweenUnit alloc] initWithObject:self.tweenView  propertyKeyPath:@\"frame.size.width\" startingValue:self.tweenView.frame.size.width endingValue:120 duration:0.9 options:PMTweenOptionNone easingBlock:easing2];\nPMTweenUnit *tween4 = [[PMTweenUnit alloc] initWithObject:self.tweenView  propertyKeyPath:@\"frame.origin.y\" startingValue:self.tweenView.frame.origin.y endingValue:100 duration:1.0 options:PMTweenOptionNone easingBlock:easing];\n\nPMTweenGroup *group = [[PMTweenGroup alloc] initWithTweens:@[tween1, tween2] options:PMTweenOptionNone];\n\nPMTweenSequence *sequence = [[PMTweenSequence alloc] initWithSequenceSteps:@[group, tween3, tween4] options:PMTweenOptionReverse|PMTweenOptionRepeat];\nsequence.reversingMode = PMTweenSequenceReversingContiguous;\n[sequence startTween];\n```\n\n**produces this animation:**\n\n![sequence](http://poetmountain.github.io/PMTween/screenshots/sequence.gif)\n\n\n### New in 1.2.0\n\nNew in the 1.2.0 release is support for additive animations in PMTweenUnit. Additive animation allows multiple tweens to produce a compound effect, instead of overwriting each other as they update the same property. Additive animation is now the default behavior for tweening animations in iOS 8, and is great for making user interface animations fluid and responsive. Of course with PMTweenUnit you are not limited to tweening UIView properties, so additive tweening may be applied to any compatible property. Simply set `additive` to YES on any PMTweenUnit instances whose tweening updates you wish to composite. Please see the documentation and updated [Examples project](https://github.com/poetmountain/PMTween/tree/master/Examples) for more information and things you should keep in mind when using this mode. Special thanks to [Andy Matuschak](https://twitter.com/andy_matuschak) and [Kevin Doughty](https://twitter.com/DoughtyKevin) for making the concept clearer.\n\n![additive](http://poetmountain.github.io/PMTween/screenshots/additive.gif)\n\n\n### New in 1.1.0\n\nNew in the 1.1.0 release is PMTweenPhysicsUnit, which provides dynamic, physics-based tweening. (Thanks to [Pop](https://github.com/facebook/pop) lib for the inspiration!) Since it adopts the PMTweening protocol, you can combine it with the other PMTween classes as you see fit.\n\nFor more information, see the included [examples](https://github.com/poetmountain/PMTween/tree/master/Examples) of PMTween usage, and peruse the [documentation](https://poetmountain.github.io/PMTween/).\n\n\n## Getting Started\n\n### Installation\n\nIf you use CocoaPods:\n\n##### Podfile\n```ruby\npod \"PMTween\", \"~\u003e 1.3.0\"\n```\n\nOr add the Classes directory to your project.\n\n\n### Examples\n\n#### Basic tween\n\nHere's the most basic type of tween, which just tweens an arbitrary data structure directly. PMTweenUnit is the workhorse tweening class in PMTween; it handles all the actual property updating. Note that nil is passed in for the easingBlock, which means it will use the default PMTweenEasingLinear easing type.\n\n```objc\n#import \u003cPMTween/PMTween.h\u003e\n\nPMTweenUnit *tween = [[PMTweenUnit alloc] initWithProperty:@(0) startingValue:0 endingValue:100 duration:1.0 options:PMTweenOptionNone easingBlock:nil];\n[tween startTween];\n```\n\nHere's another basic example. Notice that this time we've passed an options bitmask into the options parameter which will make it tween in reverse back to the starting value (after hitting the endingValue), and also repeat its tween for multiple cycles. In this case, it would repeat the total tween operation (forwards and back).\n\nWe've also defined a completeBlock, which will be called when the tween has completed all repeat cycles. Notice that the block's parameter specifies `NSObject\u003cPMTweening\u003e`, and not PMTweenUnit. It denotes that this could be any object that conforms to the PMTweening protocol. If you want to access specific properties from your tweening class that are not specified by the PMTweening protocol, you will need to cast the 'tween' object to your specific class type first.\n\n```objc\nPMTweenUnit *tween = [[PMTweenUnit alloc] initWithProperty:@(0) startingValue:0 endingValue:100 duration:1.0 options:PMTweenOptionRepeat|PMTweenOptionReverse easingBlock:nil];\ntween.completeBlock = ^void(NSObject\u003cPMTweening\u003e *tween) {\n    NSLog(@\"tween complete!\");\n};\ntween.numberOfRepeats = 2;\n[tween startTween];\n```\n\n#### Tweening an object's property\n\nA more common need is to tween an object property, such as the x position of a UIView. Check the example below. Notice that this method requires a key path. This is the object hierarchy from the object down to the property you want to tween. Even though the 'x' value can't be set directly on a frame's origin, PMTween is smart enough to handle this updating for you. PMTween handles most common UIKit properties; see the docs or the code for exactly what it supports, and let me know what it's missing.\n\nNotice also that we've defined an easingBlock this time. You can also assign a different easing block to use when reversing a tween by setting a PMTweenUnit's reverseEasingBlock property. PMTween includes all the standard Robert Penner easing types, but you can also easily use your own easing classes. Maybe you want to modify the easing by applying a Perlin noise filter or shifting the value with gyroscope data. Who knows? I don't. That's why PMTween makes it easy for you to do your own thing.\n\n```objc\nPMTweenEasingBlock easing = [PMTweenEasingCubic easingInOut];\nPMTweenUnit *tween = [[PMTweenUnit alloc] initWithObject:self.tweenView  propertyKeyPath:@\"frame.origin.x\" startingValue:self.tweenView.frame.origin.x endingValue:200 duration:1.0 options:PMTweenOptionNone easingBlock:easing];\n[tween startTween];\n```\n\n#### Using a PMTweenGroup\n\nPMTweenGroup manages multiple class instances. It's handy for controlling and synchronizing multiple tween objects. You can of course have groups within other groups.\n\nNotice in this example that a tempo object is being set on the PMTweenGroup. It provides a tempo, or in other words a rate at which the tween should update its easing calculations. This is not necessary to set unless you want to use your own custom tempo object – all PMTween tweening classes by default create their own tempo objects internally.\n\n```objc\nPMTweenEasingBlock easing = [PMTweenEasingCubic easingInOut];\nPMTweenUnit *tween = [[PMTweenUnit alloc] initWithObject:self.tweenView  propertyKeyPath:@\"frame.size.width\" startingValue:self.tweenView.frame.size.width endingValue:200 duration:1.0 options:PMTweenOptionNone easingBlock:easing];\nPMTweenUnit *tween2 = [[PMTweenUnit alloc] initWithObject:self.tweenView  propertyKeyPath:@\"frame.size.height\" startingValue:self.tweenView.frame.size.height endingValue:300 duration:2.0 options:PMTweenOptionNone easingBlock:easing];\n\nPMTweenGroup *group = [[PMTweenGroup alloc] initWithTweens:@[tween, tween2] options:PMTweenOptionReverse];\n[group setTempo:[PMTweenCATempo tempo]];\n[group startTween];\n```\n\n#### Using a PMTweenSequence\n\nPMTweenSequence plays a collection of tweens in order. Chaining tweens together is extremely easy. This is a powerful class, as you can play in sequence any assortment of PMTweenUnits, PMTweenGroups, or other PMTweenSequence classes, as well as your own custom tween classes. It's tweens all the way down. Note that we pass in an array of sequence steps – it will play the sequence in that order.\n\nWhen a PMTweenSequence is set to reverse, by default it will play as discrete elements when reversing (in other words, each child tween would just play forwards, but in reverse order). But by setting the sequence's reversingMode to PMTweenSequenceReversingContiguous you can set the whole sequence to play in reverse seamlessly, as if it was one contiguous tween. This is really great for complex animations.\n\n```objc\nPMTweenEasingBlock easing = [PMTweenEasingCubic easingInOut];\nPMTweenUnit *tween = [[PMTweenUnit alloc] initWithObject:self.tweenView  propertyKeyPath:@\"frame.origin.x\" startingValue:self.tweenView.frame.origin.x endingValue:200 duration:1.0 options:PMTweenOptionNone easingBlock:easing];\nPMTweenUnit *tween2 = [[PMTweenUnit alloc] initWithObject:self.tweenView  propertyKeyPath:@\"frame.size.height\" startingValue:self.tweenView.frame.size.height endingValue:300 duration:2.0 options:PMTweenOptionNone easingBlock:easing];\n\nPMTweenSequence *sequence = [[PMTweenSequence alloc] initWithSequenceSteps:@[tween1, tween2] options:PMTweenOptionReverse];\n[sequence startTween];\n```\n\n\n## Class reference\n\n\u003ctable\u003e\n  \u003ctr\u003e\u003cth colspan=\"2\" style=\"text-align:center;\"\u003eTween Classes\u003c/th\u003e\u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"https://poetmountain.github.io/PMTween/Classes/PMTweenUnit.html\"\u003ePMTweenUnit\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003ePMTweenUnit handles a single tween operation on an NSValue, interpolating between specified starting and ending values.\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"https://poetmountain.github.io/PMTween/Classes/PMTweenPhysicsUnit.html\"\u003ePMTweenPhysicsUnit\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003ePMTweenPhysicsUnit handles a single physics-based tween operation on an NSValue, using a physics system to update a value with decaying velocity.\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"https://poetmountain.github.io/PMTween/Classes/PMTweenGroup.html\"\u003ePMTweenGroup\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003ePMTweenGroup handles the tweening of one or more objects which conform to the PMTweening protocol, either being instances of PMTweenUnit or other custom classes. The PMTweenGroup class is a good solution when you want to easily synchronize the operation of many tweens.\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"https://poetmountain.github.io/PMTween/Classes/PMTweenSequence.html\"\u003ePMTweenSequence\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003ePMTweenSequence allows objects which conform to the PMTweening protocol to be chained together in a sequential series of tween steps.\u003c/td\u003e\n  \u003c/tr\u003e\n\n  \u003ctr\u003e\u003cth colspan=\"2\" style=\"text-align:center;\"\u003eTempo Classes\u003c/th\u003e\u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"https://poetmountain.github.io/PMTween/Classes/PMTweenCATempo.html\"\u003ePMTweenCATempo\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003ePMTweenCATempo is a concrete subclass of PMTweenTempo, and uses a CADisplayLink object to send out tempo updates that are synchronized with the refresh rate of the display.\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"https://poetmountain.github.io/PMTween/Classes/PMTweenBeat.html\"\u003ePMTweenBeat\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003ePMTweenBeat broadcasts updates from a PMTweenTempo object to multiple objects which adopt the PMTweening protocol. This allows you to use a single tempo object for all tween objects, avoiding a performance impact when tweening many objects.\u003c/td\u003e\n  \u003c/tr\u003e\n\n  \u003ctr\u003e\u003cth colspan=\"2\" style=\"text-align:center;\"\u003eEasing Types\u003c/th\u003e\u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"https://poetmountain.github.io/PMTween/Classes/PMTweenEasingLinear.html\"\u003ePMTweenEasingLinear\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003eProvides a linear easing equation.\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"https://poetmountain.github.io/PMTween/Classes/PMTweenEasingQuadratic.html\"\u003ePMTweenEasingQuadratic\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003eProvides quadratic easing equations.\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"https://poetmountain.github.io/PMTween/Classes/PMTweenEasingQuartic.html\"\u003ePMTweenEasingQuartic\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003eProvides quartic easing equations.\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"https://poetmountain.github.io/PMTween/Classes/PMTweenEasingQuintic.html\"\u003ePMTweenEasingQuintic\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003eProvides quintic easing equations.\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"https://poetmountain.github.io/PMTween/Classes/PMTweenEasingCubic.html\"\u003ePMTweenEasingCubic\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003eProvides cubic easing equations.\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"https://poetmountain.github.io/PMTween/Classes/PMTweenEasingSine.html\"\u003ePMTweenEasingSine\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003eProvides easing equations based on sine.\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"https://poetmountain.github.io/PMTween/Classes/PMTweenEasingCircular.html\"\u003ePMTweenEasingCircular\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003eProvides circular easing equations.\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"https://poetmountain.github.io/PMTween/Classes/PMTweenEasingElastic.html\"\u003ePMTweenEasingElastic\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003eProvides easing equations that behave in an elastic fashion.\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"https://poetmountain.github.io/PMTween/Classes/PMTweenEasingExpo.html\"\u003ePMTweenEasingExpo\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003eProvides exponential easing equations.\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"https://poetmountain.github.io/PMTween/Classes/PMTweenEasingBack.html\"\u003ePMTweenEasingBack\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003eProvides back easing equations.\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003ca href=\"https://poetmountain.github.io/PMTween/Classes/PMTweenEasingBounce.html\"\u003ePMTweenEasingBounce\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003eProvides easing equations that have successively smaller value peaks, like a bouncing ball.\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n\u003c/table\u003e\n\n\n## Tests\n\nPMTween is tested using [Specta](https://github.com/specta/specta)/[Expecta](https://github.com/specta/expecta/). You can install the test dependencies using CocoaPods by running 'pod install' from within the Tests directory.\n\n## Credits\n\nPMTween was created by [Brett Walker](https://twitter.com/petsound) of [Poet \u0026 Mountain](http://poetmountain.com).\n\n## Compatibility\n\n* Requires iOS 7.0 or later, tvOS 9.0 or later\n* PMTween uses ARC\n\n## License\n\nPMTween is licensed under the MIT License. I'd love to know if you use PMTween in your app!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpoetmountain%2FPMTween","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpoetmountain%2FPMTween","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpoetmountain%2FPMTween/lists"}