Skip to content

Instantly share code, notes, and snippets.

@tkafka
Created October 23, 2022 22:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tkafka/b480623a83bcead52b35582bd79902cc to your computer and use it in GitHub Desktop.
Save tkafka/b480623a83bcead52b35582bd79902cc to your computer and use it in GitHub Desktop.
A rough example of a looping SwiftUI animation
import Foundation
import SwiftUI
struct ComplicationAnimationView: View {
let titlePadding = EdgeInsets(top: 8, leading: 0, bottom: 0, trailing: 0)
var aspectRatio: CGFloat = 1.2
let imageAspectRatio: CGFloat = 757 / 224
var loopingAnimation: Animation {
Animation.linear(duration: 15).repeatForever(autoreverses: false)
}
var title: String?
@State private var frameSize = CGSize.zero
@State private var animationProgress: CGFloat = 0
var body: some View {
ZStack {
Rectangle()
.aspectRatio(aspectRatio, contentMode: .fit)
.background(Color.black)
}
/// make it fit the whole width, so that we can measure it
// .frame(idealWidth: .infinity, maxWidth: .infinity, alignment: .leading)
.measuredSize($frameSize)
.overlay(
ZStack(alignment: .bottomLeading) {
HStack(spacing: 0) {
/// repeated twice intentionally, to fill screen when animated
Image("complications-promo")
/// fill height
.resizable()
.frame(width: frameSize.height * imageAspectRatio, height: frameSize.height)
// .debugFrame(.yellow)
Image("complications-promo")
/// fill height
.resizable()
.frame(width: frameSize.height * imageAspectRatio, height: frameSize.height)
// .debugFrame(.green)
}
.frame(width: frameSize.height * imageAspectRatio * 2, height: frameSize.height)
.offset(
x: -1 * frameSize.height * imageAspectRatio * animationProgress,
y: frameSize.height * 0.4
)
.rotationEffect(.degrees(10))
.scaleEffect(1.20)
.onAppear {
withAnimation(loopingAnimation) {
self.animationProgress = 1
}
}
Image("overlay-black-to-bottom")
/// fill width
.resizable()
.frame(width: frameSize.width, height: frameSize.height, alignment: .bottom)
if let title = title {
Text(title.localizedUppercase)
.textStyle(fontSize: .large, weight: .bold)
.frame(idealWidth: frameSize.width, maxWidth: frameSize.width, alignment: .bottomLeading)
.padding(titlePadding)
} /// title
} /// zstack
.frame(width: frameSize.width, height: frameSize.height, alignment: .topLeading)
.clipShape(Rectangle())
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment