animatable

Форк
0

4 месяца назад
4 месяца назад
4 месяца назад
2 года назад
2 года назад
README.md

Animatable

Latest release

contact: @lexkraev Telegram Group

Yet another animation modifiers for buttons, skeletons and other views on pure SwiftUI.

Demo example for card skeletons

🔍 Full demo video you can find here.

👨🏻‍💻 Feel free to subscribe to channel SwiftUI dev in telegram.

Requirements

  • iOS 13.0 or macOS 10.15

Installation

Swift Package Manager

To integrate Animatable into your project using SwiftPM add the following to your Package.swift:

dependencies: [
.package(url: "https://github.com/c-villain/Animatable", from: "0.1.0"),
],

or via XcodeGen insert into your 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

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

live comments

Use .animate(.liveComments(stamps:),animate:) where stamps is number of prints in animation activity, animate is flag to start animation.

@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)
)
}
Explosion effect

explosion

Use .animate(.explosive(color:),animate:) where color is color of explosion in animation activity, animate is flag to start animation.

@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)
)
}
Tweak effect

tweak

Use .animate(.tweaking(amount:,shakesPerUnit:),animate:) where amount is tweak offset, shakesPerUnit is number of shakes in tweking, animate is flag to start animation.

@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)
)
}
Scaling effect

scaling

Use .animate(.scaling(scaling:),animate:) where scaling is scaling factor, animate is flag to start animation.

@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)
)
}
Rotating effect

scaling

Use .animate(.rotating,animate:) where animate is flag to start animation.

@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)
)
}
Fireworks effect

fireworks

Use .animate(.fireworks(color:),animate:) where color is color of animation, animate is flag to start animation.

@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.

Combining animation

combined

Use sequence of .animate(type:,animate:) to get multiple animation effect.

@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)
)
}

👇🏻 Animation for skeletons and other views.

Shimmers

combined

Use sequence of .shimmerable(configuration:) where configuration is settings for for shimmers or .shimmerable() for defaults

Rectangle()
.fill(.pink.opacity(0.8))
.frame(height: 40)
.frame(maxWidth: .infinity)
.shimmerable()
.cornerRadius(12)
Blinking

combined

Use sequence of .blinking(configuration:) where configuration is settings for for blinking animation or .blinking() for defaults

Rectangle()
.fill(.pink.opacity(0.8))
.frame(height: 40)
.frame(maxWidth: .infinity)
.blinking()
.cornerRadius(12)
Combining blinking and shimmerable

combined

Use sequence of .blinking() and .shimmerable() to get multiple animation effect.

Rectangle()
.fill(.pink.opacity(0.8))
.frame(height: 40)
.frame(maxWidth: .infinity)
.blinking()
.shimmerable()
.cornerRadius(12)

⚠️ Recommendations for use

with combining animation

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:

problem1

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:

erro1

with group of views

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)
)
}

The result:

example1

with standart SUI modifiers

Be careful with standard SUI modifiers. It may cause different side effects.

For example cornerRadius crops the modified view.

@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!
}

The result:

problem2

I recommend you to use it in the .background to get expected behaviour:

.background ( // <== Look here
Rectangle()
.fill(.blue.opacity(0.8))
.cornerRadius(12) // <== Look here
)

Communication

  • If you like this repository, please do :star: to make this useful for others.
  • If you found a bug, open an issue or submit a fix via a pull request.
  • If you have a feature request, open an issue or submit a implementation via a pull request or hit me up on lexkraev@gmail.com or telegram.
  • If you want to contribute, submit a pull request onto the master branch.

License

Animatable package is released under an MIT license.

Описание

Yet another animation modifiers (like fireworks, live comments or explosion) on SwiftUI

Языки

Swift

Сообщить о нарушении

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.