mirror of
https://github.com/EmergeTools/Pow.git
synced 2026-03-25 08:55:50 +00:00
149 lines
4.7 KiB
Swift
149 lines
4.7 KiB
Swift
import SwiftUI
|
|
|
|
public extension AnyTransition.MovingParts {
|
|
/// A transition that removes the view in a dissolving cartoon style cloud.
|
|
///
|
|
/// The transition is only performed on removal and takes 0.4 seconds.
|
|
static var poof: AnyTransition {
|
|
.asymmetric(
|
|
insertion: .identity,
|
|
removal: .modifier(
|
|
active: Poof(animatableData: 0),
|
|
identity: Poof(animatableData: 1)
|
|
)
|
|
.animation(.linear(duration: 0.4))
|
|
)
|
|
}
|
|
}
|
|
|
|
struct Poof: ViewModifier, ProgressableAnimation, AnimatableModifier {
|
|
var animatableData: CGFloat = 0
|
|
|
|
internal init(animatableData: CGFloat) {
|
|
self.animatableData = animatableData
|
|
}
|
|
|
|
func body(content: Content) -> some View {
|
|
let frame = (6 * progress).rounded()
|
|
|
|
content
|
|
.opacity(progress != 1 ? 0 : 1)
|
|
.overlay(
|
|
ZStack {
|
|
poof("poof1").opacity(frame == 5 ? 1 : 0)
|
|
poof("poof2").opacity(frame == 4 ? 1 : 0)
|
|
poof("poof3").opacity(frame == 3 ? 1 : 0)
|
|
poof("poof4").opacity(frame == 2 ? 1 : 0)
|
|
poof("poof5").opacity(frame == 1 ? 1 : 0)
|
|
|
|
}
|
|
.accessibilityHidden(true)
|
|
)
|
|
.animation(nil, value: progress)
|
|
}
|
|
|
|
func poof(_ name: String) -> some View {
|
|
Image(name, bundle: .module)
|
|
.resizable()
|
|
.aspectRatio(contentMode: .fit)
|
|
.frame(width: 88, height: 88)
|
|
}
|
|
}
|
|
|
|
#if os(iOS) && DEBUG
|
|
struct Proof_Preview: PreviewableAnimation, PreviewProvider {
|
|
static var animation: Poof {
|
|
Poof(animatableData: 0)
|
|
}
|
|
|
|
static var content: any View {
|
|
ZStack {
|
|
RoundedRectangle(cornerRadius: 32, style: .continuous)
|
|
.fill(Color.accentColor)
|
|
|
|
Text("Hello\nWorld!")
|
|
.foregroundColor(.white)
|
|
.multilineTextAlignment(.center)
|
|
.font(.system(.title, design: .rounded))
|
|
}
|
|
.frame(width: 300, height: 150)
|
|
}
|
|
}
|
|
|
|
@available(iOS 15.0, *)
|
|
struct Poof_Previews: PreviewProvider {
|
|
struct Preview: View {
|
|
@State
|
|
var indices: [UUID] = [UUID()]
|
|
|
|
var body: some View {
|
|
ScrollView {
|
|
VStack(alignment: .leading, spacing: 12) {
|
|
VStack(alignment: .leading, spacing: 12) {
|
|
Text("Poof")
|
|
.bold()
|
|
|
|
Text("myView.transition(.movingParts.poof)")
|
|
}
|
|
.font(.footnote.monospaced())
|
|
.frame(maxWidth: .greatestFiniteMagnitude, alignment: .leading)
|
|
.padding()
|
|
.background(
|
|
RoundedRectangle(cornerRadius: 8, style: .continuous)
|
|
.fill(.thickMaterial)
|
|
)
|
|
|
|
Stepper {
|
|
Text("View Count ") + Text("(\(indices.count))").foregroundColor(.secondary)
|
|
} onIncrement: {
|
|
withAnimation {
|
|
indices.append(UUID())
|
|
}
|
|
} onDecrement: {
|
|
if !indices.isEmpty {
|
|
let _ = withAnimation {
|
|
indices.removeLast()
|
|
}
|
|
}
|
|
}
|
|
|
|
let columns: [GridItem] = [
|
|
.init(.flexible()),
|
|
.init(.flexible())
|
|
]
|
|
|
|
LazyVGrid(columns: columns) {
|
|
ForEach(indices, id: \.self) { uuid in
|
|
ZStack {
|
|
RoundedRectangle(cornerRadius: 32, style: .continuous)
|
|
.fill(Color.accentColor)
|
|
|
|
Text("Hello\nWorld!")
|
|
.foregroundColor(.white)
|
|
.multilineTextAlignment(.center)
|
|
.font(.system(.title, design: .rounded))
|
|
|
|
}
|
|
.transition(
|
|
.movingParts.poof
|
|
)
|
|
.aspectRatio(2, contentMode: .fit)
|
|
.id(uuid)
|
|
}
|
|
}
|
|
|
|
Spacer()
|
|
}
|
|
.padding()
|
|
}
|
|
}
|
|
}
|
|
|
|
static var previews: some View {
|
|
NavigationView {
|
|
Preview()
|
|
.navigationBarHidden(true)
|
|
}
|
|
}
|
|
}
|
|
#endif
|