{"id":13414587,"url":"https://github.com/material-motion/material-motion-swift","last_synced_at":"2025-09-30T13:32:05.663Z","repository":{"id":61529185,"uuid":"75793536","full_name":"material-motion/material-motion-swift","owner":"material-motion","description":"A toolkit for building responsive motion using Core Animation.","archived":true,"fork":false,"pushed_at":"2020-02-04T07:25:37.000Z","size":14490,"stargazers_count":1422,"open_issues_count":56,"forks_count":80,"subscribers_count":43,"default_branch":"develop","last_synced_at":"2025-01-15T23:04:28.289Z","etag":null,"topics":["animation","gesture-driven-animations","ios","motion","reactive","swift","transitions"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/material-motion.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-12-07T03:01:17.000Z","updated_at":"2024-12-12T10:41:53.000Z","dependencies_parsed_at":"2022-10-19T04:15:19.270Z","dependency_job_id":null,"html_url":"https://github.com/material-motion/material-motion-swift","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/material-motion%2Fmaterial-motion-swift","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/material-motion%2Fmaterial-motion-swift/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/material-motion%2Fmaterial-motion-swift/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/material-motion%2Fmaterial-motion-swift/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/material-motion","download_url":"https://codeload.github.com/material-motion/material-motion-swift/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234744628,"owners_count":18879955,"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","gesture-driven-animations","ios","motion","reactive","swift","transitions"],"created_at":"2024-07-30T21:00:29.515Z","updated_at":"2025-09-30T13:32:04.693Z","avatar_url":"https://github.com/material-motion.png","language":"Swift","readme":"# Material Motion\n\n\u003e Reactive motion driven by Core Animation.\n\n![Swift 3.1.x](https://img.shields.io/badge/Swift-3.1.x-orange.svg)\n![iOS 9.0+](https://img.shields.io/badge/iOS-9.0+-orange.svg)\n[![Build Status](https://travis-ci.org/material-motion/material-motion-swift.svg?branch=develop)](https://travis-ci.org/material-motion/material-motion-swift)\n[![codecov](https://codecov.io/gh/material-motion/material-motion-swift/branch/develop/graph/badge.svg)](https://codecov.io/gh/material-motion/material-motion-swift)\n[![CocoaPods Compatible](https://img.shields.io/cocoapods/v/MaterialMotion.svg)](https://cocoapods.org/pods/MaterialMotion)\n[![Platform](https://img.shields.io/cocoapods/p/MaterialMotion.svg)](http://cocoadocs.org/docsets/MaterialMotion)\n[![Docs](https://img.shields.io/cocoapods/metrics/doc-percent/MaterialMotion.svg)](http://cocoadocs.org/docsets/MaterialMotion)\n[![Chat](https://img.shields.io/discord/198544450366996480.svg)](https://discord.gg/material-motion)\n\nThis library includes a variety of ready-to-use **interactions**. Interactions are registered to an\ninstance of `MotionRuntime`:\n\n```swift\n// Store me for as long as the interactions should take effect.\nlet runtime = MotionRuntime(containerView: \u003c#view#\u003e)\n```\n\n\u003ctable\u003e\n  \u003cthead\u003e\u003ctr\u003e\u003cth\u003e\u003c/th\u003e\u003cth\u003eInteraction\u003c/th\u003e\u003cth\u003eSnippet\u003c/th\u003e\u003c/tr\u003e\u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\"\u003e\u003cimg src=\"assets/arcmove.gif\" /\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003cpre\u003e\u003ccode class=\"language-swift\"\u003eArcMove\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003cpre\u003e\u003ccode class=\"language-swift\"\u003elet arcMove = ArcMove()\narcMove.from.value = \u003c#from#\u003e\narcMove.to.value = \u003c#to#\u003e\nruntime.add(arcMove, to: \u003c#view#\u003e)\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\"\u003e\u003cimg src=\"assets/changedirection.gif\" /\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003cpre\u003e\u003ccode class=\"language-swift\"\u003eChangeDirection\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003cpre\u003e\u003ccode class=\"language-swift\"\u003eruntime.add(ChangeDirection(withVelocityOf: gesture),\n            to: \u003c#direction#\u003e)\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\"\u003e\u003cimg src=\"assets/directlymanipulable.gif\" /\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003cpre\u003e\u003ccode class=\"language-swift\"\u003eDirectlyManipulable\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003cpre\u003e\u003ccode class=\"language-swift\"\u003eruntime.add(DirectlyManipulable(), to: \u003c#view#\u003e)\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\"\u003e\u003cimg src=\"assets/draggable.gif\" /\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003cpre\u003e\u003ccode class=\"language-swift\"\u003eDraggable\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003cpre\u003e\u003ccode class=\"language-swift\"\u003eruntime.add(Draggable(), to: \u003c#view#\u003e)\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\"\u003e\u003cimg src=\"assets/rotatable.gif\" /\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003cpre\u003e\u003ccode class=\"language-swift\"\u003eRotatable\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003cpre\u003e\u003ccode class=\"language-swift\"\u003eruntime.add(Rotatable(), to: \u003c#view#\u003e)\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\"\u003e\u003cimg src=\"assets/scalable.gif\" /\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003cpre\u003e\u003ccode class=\"language-swift\"\u003eScalable\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003cpre\u003e\u003ccode class=\"language-swift\"\u003eruntime.add(Scalable(), to: \u003c#view#\u003e)\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\"\u003e\u003cimg src=\"assets/setpositionontap.gif\" /\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003cpre\u003e\u003ccode class=\"language-swift\"\u003eSetPositionOnTap\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003cpre\u003e\u003ccode class=\"language-swift\"\u003eruntime.add(SetPositionOnTap(),\n            to: runtime.get(\u003c#view#\u003e.layer).position)\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\"\u003e\u003cimg src=\"assets/spring.gif\" /\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003cpre\u003e\u003ccode class=\"language-swift\"\u003eSpring\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003cpre\u003e\u003ccode class=\"language-swift\"\u003elet spring = Spring()\nspring.destination.value = \u003c#initial destination#\u003e\nruntime.add(spring, to: \u003c#view#\u003e)\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\"\u003e\u003cimg src=\"assets/tossable.gif\" /\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003cpre\u003e\u003ccode class=\"language-swift\"\u003eTossable\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003cpre\u003e\u003ccode class=\"language-swift\"\u003elet tossable = Tossable()\ntossable.spring.destination.value = \u003c#initial destination#\u003e\nruntime.add(tossable, to: \u003c#view#\u003e)\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\"\u003e\u003cimg src=\"assets/tween.gif\" /\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003cpre\u003e\u003ccode class=\"language-swift\"\u003eTween\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n      \u003ctd\u003e\u003cpre\u003e\u003ccode class=\"language-swift\"\u003eruntime.add(Tween(duration: 0.5, values: [1, 0]),\n            to: runtime.get(\u003c#view#\u003e.layer).opacity)\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n## Installation\n\n### Installation with CocoaPods\n\n\u003e CocoaPods is a dependency manager for Objective-C and Swift libraries. CocoaPods automates the\n\u003e process of using third-party libraries in your projects. See\n\u003e [the Getting Started guide](https://guides.cocoapods.org/using/getting-started.html) for more\n\u003e information. You can install it with the following command:\n\u003e\n\u003e     gem install cocoapods\n\nAdd `MaterialMotion` to your `Podfile`:\n\n```ruby\npod 'MaterialMotion'\n```\n\nYou will need to add `use_frameworks!` to your Podfile in order use Material Motion in your swift\napp.\n\nA simple Podfile might look like so:\n\n```ruby\nproject 'MyApp/MyApp.xcodeproj'\n\nuse_frameworks!\n\ntarget 'MyApp' do\n  pod 'MaterialMotion'\nend\n```\n\nThen run the following command:\n\n```bash\npod install\n```\n\n### Usage\n\nImport the framework:\n\n```swift\nimport MaterialMotion\n```\n\nYou will now have access to all of the APIs.\n\n## Example apps/unit tests\n\nCheck out a local copy of the repo to access the Catalog application by running the following\ncommands:\n\n```bash\ngit clone https://github.com/material-motion/material-motion-swift.git\ncd material-motion-swift\npod install\nopen MaterialMotion.xcworkspace\n```\n\n## Case studies\n\n### Carousel\n\n\u003cimg src=\"assets/carousel.gif\" /\u003e\n\nA carousel with pages that scale in and fade out in reaction to their scroll position.\n\n[View the source](examples/CarouselExample.swift).\n\n### Contextual transition\n\n\u003cimg src=\"assets/contextualtransition.gif\" /\u003e\n\nA contextual view can be used to create continuity during transitions between view controllers. In\nthis case study the selected photo is the contextual view. It's  possible to flick the view to\ndismiss it using the tossable interaction.\n\nMakes use of: `Draggable`, `Tossable`, `Transition`, `TransitionSpring`, `Tween`.\n\n[View the source](examples/ContextualTransitionExample.swift).\n\n### Floating action button transition\n\n\u003cimg src=\"assets/fabtransition.gif\" /\u003e\n\nA floating action button transition is a type of contextual transition that animates a mask outward\nfrom a floating button.\n\nMakes use of: `Transition` and `Tween`.\n\n[View the source](examples/FabTransitionExample.swift).\n\n### Material expansion\n\n\u003cimg src=\"assets/materialexpansion.gif\" /\u003e\n\nA Material Design transition using asymetric transformations.\n\nMakes use of: `Tween`.\n\n[View the source](examples/MaterialExpansionExample.swift).\n\n### Modal dialog\n\n\u003cimg src=\"assets/modaldialog.gif\" /\u003e\n\nA modal dialog that's presented over the existing context and is dismissable using gestures.\n\nMakes use of: `Tossable` and `TransitionSpring`.\n\n[View the source](examples/ModalDialogExample.swift).\n\n### Pull down to dismiss\n\n\u003cimg src=\"assets/pulldowntodismiss.gif\" /\u003e\n\nA modal scroll view controller that can be dismissed with a drag gesture.\n\nMakes use of: `Tossable` and `TransitionSpring`.\n\n[View the source](examples/InteractivePushBackTransitionExample.swift).\n\n### Sticker picker\n\n\u003cimg src=\"assets/stickerpicker.gif\" /\u003e\n\nEach sticker is individually **directly manipulable**, meaning they can be dragged, rotated, and\nscaled using multitouch gestures.\n\nMakes use of: `DirectlyManipulable`.\n\n[View the source](examples/StickerPickerExample.swift).\n\n## Contributing\n\nWe welcome contributions!\n\nCheck out our [upcoming milestones](https://github.com/material-motion/material-motion-swift/milestones).\n\nLearn more about [our team](https://material-motion.github.io/material-motion/team/),\n[our community](https://material-motion.github.io/material-motion/team/community/), and\nour [contributor essentials](https://material-motion.github.io/material-motion/team/essentials/).\n\n## License\n\nLicensed under the Apache 2.0 license. See LICENSE for details.\n","funding_links":[],"categories":["Animations","iOS","Swift","transitions"],"sub_categories":["Components"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaterial-motion%2Fmaterial-motion-swift","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaterial-motion%2Fmaterial-motion-swift","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaterial-motion%2Fmaterial-motion-swift/lists"}