Update README.md
Yet another animation modifiers for buttons on pure SwiftUI.
🔍 Full demo video you can find here.
👨🏻💻 Feel free to subscribe to channel SwiftUI dev in telegram.
To integrate Animatable into your project using SwiftPM add the following to your Package.swift:
Animatable
Package.swift
dependencies: [ .package(url: "https://github.com/c-villain/Animatable", from: "0.1.0"), ],
or via XcodeGen insert into your project.yml:
project.yml
name: YourProjectName options: deploymentTarget: iOS: 13.0 packages: Animatable: url: https://github.com/c-villain/Animatable from: 0.1.0 targets: YourTarget: type: application ... dependencies: - package: Animatable
All examples you can find in demo project inside package.
There are different custom animation types provided by Animatable.
👇🏻 Tap on its name to see description and example of using.
Use .animate(.liveComments(stamps:),animate:) where stamps is number of prints in animation activity, animate is flag to start animation.
.animate(.liveComments(stamps:),animate:)
stamps
animate
@State var animate: Bool = false ... Button { animate.toggle() } label: { HStack(spacing: 8) { Image(systemName: animate ? "heart.fill" : "heart") .resizable() .scaledToFit() .animate(.liveComments(stamps: 4), animate: animate) .frame(width: 24, height: 24) .foregroundColor(.white) Text("Like") .font(.body) .fontWeight(.medium) .foregroundColor(.white) } .padding(12) .background( Rectangle() .fill(.pink.opacity(0.8)) .cornerRadius(12) ) }
Use .animate(.explosive(color:),animate:) where color is color of explosion in animation activity, animate is flag to start animation.
.animate(.explosive(color:),animate:)
color
@State var animate: Bool = false ... Button { animate.toggle() } label: { HStack(spacing: 8) { Image(systemName: animate ? "power" : "poweroff") .resizable() .scaledToFit() .animate(.explosive(color: .white), animate: animate) .frame(width: 24, height: 24) .foregroundColor(.white) Text(animate ? "On" : "Off") .font(.body) .fontWeight(.medium) .foregroundColor(.white) } .padding(12) .background( Rectangle() .fill(.gray.opacity(0.8)) .cornerRadius(12) ) }
Use .animate(.tweaking(amount:,shakesPerUnit:),animate:) where amount is tweak offset, shakesPerUnit is number of shakes in tweking, animate is flag to start animation.
.animate(.tweaking(amount:,shakesPerUnit:),animate:)
amount
shakesPerUnit
@State var animate: Bool = false ... Button { animate.toggle() } label: { HStack(spacing: 8) { Image(systemName: animate ? "hand.thumbsup.fill" : "hand.thumbsup") .resizable() .scaledToFit() .animate(.tweaking(), animate: animate) .frame(width: 24, height: 24) .foregroundColor(.white) Text("Like") .font(.body) .fontWeight(.medium) .foregroundColor(.white) } .padding(12) .background( Rectangle() .fill(.blue.opacity(0.8)) .cornerRadius(12) ) }
Use .animate(.scaling(scaling:),animate:) where scaling is scaling factor, animate is flag to start animation.
.animate(.scaling(scaling:),animate:)
scaling
@State var animate: Bool = false ... Button { animate.toggle() } label: { HStack(spacing: 8) { Image(systemName: animate ? "plus.app.fill" : "plus.app") .resizable() .scaledToFit() .animate(.scaling(), animate: animate) .frame(width: 24, height: 24) .foregroundColor(.white) Text("Add") .font(.body) .fontWeight(.medium) .foregroundColor(.white) } .padding(12) .background( Rectangle() .fill(.yellow.opacity(0.8)) .cornerRadius(12) ) }
Use .animate(.rotating,animate:) where animate is flag to start animation.
.animate(.rotating,animate:)
@State var animate: Bool = false ... Button { animate.toggle() } label: { HStack(spacing: 8) { Image(systemName: animate ? "arrow.triangle.2.circlepath.circle.fill" : "arrow.triangle.2.circlepath.circle") .resizable() .scaledToFit() .animate(.rotating, animate: animate) .frame(width: 24, height: 24) .foregroundColor(.white) Text("Sync") .font(.body) .fontWeight(.medium) .foregroundColor(.white) } .padding(12) .background( Rectangle() .fill(.blue.opacity(0.8)) .cornerRadius(12) ) }
Use .animate(.fireworks(color:),animate:) where color is color of animation, animate is flag to start animation.
.animate(.fireworks(color:),animate:)
@State var animate: Bool = false ... Button { animate.toggle() } label: { HStack(spacing: 8) { Image(systemName: animate ? "sun.max.fill" : "sun.max") .resizable() .scaledToFit() .animate(.fireworks(color: .white), animate: animate) .frame(width: 24, height: 24) .foregroundColor(.white) Text("Weather") .font(.body) .fontWeight(.medium) .foregroundColor(.white) } .padding(12) .background( Rectangle() .fill(.blue.opacity(0.8)) .cornerRadius(12) ) }
👇🏻 You can easily join them together to combine animation.
Use sequence of .animate(type:,animate:) to get multiple animation effect.
.animate(type:,animate:)
@State var animate: Bool = false ... Button { animate.toggle() } label: { HStack(spacing: 8) { Image(systemName: animate ? "sun.max.fill" : "sun.max") .resizable() .scaledToFit() .animate(.rotating, animate: animate) .animate(.explosive(color: .red, factor: 2.0), animate: animate) .animate(.explosive(color: .blue, factor: 1.4), animate: animate) .animate(.fireworks(color: .yellow, factor: 3.5), animate: animate) .frame(width: 24, height: 24) .foregroundColor(.red) Text("Combined") .font(.body) .fontWeight(.medium) .foregroundColor(.white) } .padding(12) .background( Rectangle() .fill(.blue.opacity(0.6)) .cornerRadius(12) ) }
Order in sequence of .animate(type:,animate:) is really important!
Feel the difference in the next example:
@State var animate: Bool = false ... Button { animate.toggle() } label: { HStack(spacing: 8) { Image(systemName: multiple ? "sun.max.fill" : "sun.max") .resizable() .scaledToFit() .animate(.liveComments(stamps: 4), animate: animate) .animate(.rotating, animate: animate) .animate(.explosive(color: .red, factor: 2.0), animate: animate) .animate(.explosive(color: .blue, factor: 1.4), animate: animate) .animate(.fireworks(color: .yellow, factor: 3.0), animate: animate) .frame(width: 24, height: 24) .foregroundColor(.red) Text("Weather") .font(.body) .fontWeight(.medium) .foregroundColor(.white) } .padding(12) .background( Rectangle() .fill(.blue.opacity(0.6)) .cornerRadius(12) ) }
Using this sequence of .animate(...) leads to such behaviour:
.animate(...)
To get expected behaviour this we should change the order in chain:
@State var animate: Bool = false ... Button { animate.toggle() } label: { HStack(spacing: 8) { Image(systemName: multiple ? "sun.max.fill" : "sun.max") .resizable() .scaledToFit() .animate(.rotating, // <== Look here! animate: animate) .animate(.liveComments(stamps: 4), // <== Look here! animate: animate) .animate(.explosive(color: .red, factor: 2.0), animate: animate) .animate(.explosive(color: .blue, factor: 1.4), animate: animate) .animate(.fireworks(color: .yellow, factor: 3.0), animate: animate) .frame(width: 24, height: 24) .foregroundColor(.red) Text("Weather") .font(.body) .fontWeight(.medium) .foregroundColor(.white) } .padding(12) .background( Rectangle() .fill(.blue.opacity(0.6)) .cornerRadius(12) ) }
The result:
Use can use .animate(...) not only for one view but for group of views
@State var animate: Bool = false ... Button { animate.toggle() } label: { HStack(spacing: 8) { Image(systemName: animate ? "heart.fill" : "heart") .resizable() .scaledToFit() .frame(width: 24, height: 24) .foregroundColor(.red) Text("Like") .font(.body) .fontWeight(.medium) .foregroundColor(.red) } .animate(.liveComments(stamps: 4), // <== Look here! animate: animate) .padding(12) .background( Rectangle() .fill(.blue.opacity(0.8)) .cornerRadius(12) ) }
Be careful with standard SUI modifiers. It may cause different side effects.
For example cornerRadius crops the modified view.
cornerRadius
@State var animate: Bool = false ... Button { animate.toggle() } label: { HStack(spacing: 8) { Image(systemName: liveComments ? "heart.fill" : "heart") .resizable() .scaledToFit() .animate(.liveComments(stamps: 4), animate: animate) .frame(width: 24, height: 24) .foregroundColor(.red) Text("Like") .font(.body) .fontWeight(.medium) .foregroundColor(.white) } .padding(12) .background ( Color.blue.opacity(0.8) ) .cornerRadius(12) // <== Look here! }
I recommend you to use it in the .background to get expected behaviour:
.background
.background ( // <== Look here Rectangle() .fill(.blue.opacity(0.8)) .cornerRadius(12) // <== Look here )
Animatable package is released under an MIT license.
©Copyright 2023 CCF 开源发展委员会 Powered by Trustie& IntelliDE 京ICP备13000930号
Animatable
Yet another animation modifiers for buttons on pure SwiftUI.
🔍 Full demo video you can find here.
👨🏻💻 Feel free to subscribe to channel SwiftUI dev in telegram.
Requirements
Installation
Swift Package Manager
To integrate
Animatable
into your project using SwiftPM add the following to yourPackage.swift
:or via XcodeGen insert into your
project.yml
:Quick start
All examples you can find in demo project inside package.
There are different custom animation types provided by
Animatable
.👇🏻 Tap on its name to see description and example of using.
Live comments effect
Use
.animate(.liveComments(stamps:),animate:)
wherestamps
is number of prints in animation activity,animate
is flag to start animation.Explosion effect
Use
.animate(.explosive(color:),animate:)
wherecolor
is color of explosion in animation activity,animate
is flag to start animation.Tweak effect
Use
.animate(.tweaking(amount:,shakesPerUnit:),animate:)
whereamount
is tweak offset,shakesPerUnit
is number of shakes in tweking,animate
is flag to start animation.Scaling effect
Use
.animate(.scaling(scaling:),animate:)
wherescaling
is scaling factor,animate
is flag to start animation.Rotating effect
Use
.animate(.rotating,animate:)
whereanimate
is flag to start animation.Fireworks effect
Use
.animate(.fireworks(color:),animate:)
wherecolor
is color of animation,animate
is flag to start animation.👇🏻 You can easily join them together to combine animation.
Combining animation
Use sequence of
.animate(type:,animate:)
to get multiple animation effect.⚠️ Recommendations for use
with combining animation
Order in sequence of
.animate(type:,animate:)
is really important!Feel the difference in the next example:
Using this sequence of
.animate(...)
leads to such behaviour:To get expected behaviour this we should change the order in chain:
The result:
with group of views
Use can use
.animate(...)
not only for one view but for group of viewsThe result:
with standart SUI modifiers
Be careful with standard SUI modifiers. It may cause different side effects.
For example
cornerRadius
crops the modified view.The result:
I recommend you to use it in the
.background
to get expected behaviour:Communication
License
Animatable package is released under an MIT license.