mirror of
https://github.com/EmergeTools/Pow.git
synced 2026-03-25 08:55:50 +00:00
Add snapshots
This commit is contained in:
parent
897afcde74
commit
7574e15bb7
14 changed files with 229 additions and 62 deletions
62
Sources/Pow/Infrastructure/ProgressableAnimation.swift
Normal file
62
Sources/Pow/Infrastructure/ProgressableAnimation.swift
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
//
|
||||
// ProgressableAnimation.swift
|
||||
//
|
||||
//
|
||||
// Created by Noah Martin on 11/30/23.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
#if DEBUG
|
||||
typealias DebugProgressableAnimation = ProgressableAnimation
|
||||
#else
|
||||
typealias DebugProgressableAnimation = Animatable
|
||||
#endif
|
||||
|
||||
protocol ProgressableAnimation: Animatable {
|
||||
var progress: CGFloat { get set }
|
||||
}
|
||||
|
||||
extension ProgressableAnimation where AnimatableData == CGFloat {
|
||||
var progress: CGFloat {
|
||||
get { animatableData }
|
||||
set { animatableData = newValue }
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
protocol PreviewableAnimation {
|
||||
associatedtype Animation: ProgressableAnimation & ViewModifier
|
||||
|
||||
static var animation: Animation { get }
|
||||
|
||||
static var content: any View { get }
|
||||
}
|
||||
|
||||
extension PreviewableAnimation {
|
||||
static var content: any View {
|
||||
RoundedRectangle(
|
||||
cornerRadius: 8,
|
||||
style: .continuous)
|
||||
.fill(Color.blue)
|
||||
.frame(width: 80, height: 80)
|
||||
}
|
||||
}
|
||||
|
||||
extension PreviewableAnimation {
|
||||
static var previews: AnyView {
|
||||
let c = self.content
|
||||
let anyContent = AnyView(c)
|
||||
let modifiers = [0, 0.25, 0.5, 0.75, 1].map { i in
|
||||
var copy = self.animation
|
||||
copy.progress = i
|
||||
return copy
|
||||
}
|
||||
return AnyView(ForEach(Array(modifiers.enumerated()), id: \.offset) { i, modifier in
|
||||
anyContent.modifier(modifier)
|
||||
.previewDisplayName("\(String(describing: Animation.self))-\(i)")
|
||||
})
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -26,3 +26,5 @@ internal struct Scaled<V: ViewModifier & Animatable>: ViewModifier, Animatable {
|
|||
content.modifier(base.animation(nil))
|
||||
}
|
||||
}
|
||||
|
||||
extension Scaled: ProgressableAnimation where V.AnimatableData == CGFloat { }
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ public extension AnyTransition.MovingParts {
|
|||
}
|
||||
}
|
||||
|
||||
internal struct Anvil: ViewModifier, Animatable, AnimatableModifier {
|
||||
internal struct Anvil: ViewModifier, ProgressableAnimation, AnimatableModifier {
|
||||
var animatableData: CGFloat = 0
|
||||
|
||||
#if os(iOS)
|
||||
|
|
@ -31,11 +31,6 @@ internal struct Anvil: ViewModifier, Animatable, AnimatableModifier {
|
|||
self.animatableData = animatableData
|
||||
}
|
||||
|
||||
var progress: CGFloat {
|
||||
get { animatableData }
|
||||
set { animatableData = newValue }
|
||||
}
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
/// Fraction of the animation spent on the view falling down.
|
||||
let fall: CGFloat = 0.1
|
||||
|
|
@ -212,6 +207,21 @@ extension EdgeInsets {
|
|||
}
|
||||
|
||||
#if os(iOS) && DEBUG
|
||||
struct Anvil_Preview: PreviewableAnimation, PreviewProvider {
|
||||
static var animation: Anvil {
|
||||
Anvil(animatableData: 0)
|
||||
}
|
||||
|
||||
static var content: any View {
|
||||
RoundedRectangle(
|
||||
cornerRadius: 8,
|
||||
style: .continuous)
|
||||
.fill(Color.blue)
|
||||
.frame(width: 80, height: 80)
|
||||
.preferredColorScheme(.dark)
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 15.0, *)
|
||||
struct Anvil_Previews: PreviewProvider {
|
||||
struct Item: Identifiable {
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ public extension AnyTransition.MovingParts {
|
|||
}
|
||||
}
|
||||
|
||||
internal struct Blinds: ViewModifier, Animatable, AnimatableModifier, Hashable {
|
||||
internal struct Blinds: ViewModifier, ProgressableAnimation, AnimatableModifier, Hashable {
|
||||
var slatWidth: CGFloat
|
||||
|
||||
var style: AnyTransition.MovingParts.BlindsStyle
|
||||
|
|
@ -39,11 +39,6 @@ internal struct Blinds: ViewModifier, Animatable, AnimatableModifier, Hashable {
|
|||
|
||||
var animatableData: CGFloat
|
||||
|
||||
private var progress: CGFloat {
|
||||
get { animatableData }
|
||||
set { animatableData = newValue }
|
||||
}
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
content
|
||||
.mask {
|
||||
|
|
@ -108,6 +103,13 @@ private struct BlindsShape: Shape {
|
|||
}
|
||||
|
||||
#if os(iOS) && DEBUG
|
||||
struct Blinds_Preview: PreviewableAnimation & PreviewProvider {
|
||||
|
||||
static var animation: Blinds {
|
||||
Blinds(slatWidth: 20, style: .venetian, isStaggered: false, animatableData: 0)
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 15.0, *)
|
||||
struct Blinds_Previews: PreviewProvider {
|
||||
struct Preview: View {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ public extension AnyTransition.MovingParts {
|
|||
}
|
||||
}
|
||||
|
||||
internal struct Blur: ViewModifier, Animatable, AnimatableModifier, Hashable {
|
||||
internal struct Blur: ViewModifier, DebugProgressableAnimation, AnimatableModifier, Hashable {
|
||||
var animatableData: CGFloat {
|
||||
get { radius }
|
||||
set { radius = newValue }
|
||||
|
|
@ -37,6 +37,12 @@ internal struct Blur: ViewModifier, Animatable, AnimatableModifier, Hashable {
|
|||
}
|
||||
|
||||
#if os(iOS) && DEBUG
|
||||
struct Blur_Preview: PreviewableAnimation, PreviewProvider {
|
||||
static var animation: Blur {
|
||||
Blur(radius: 30)
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 15.0, *)
|
||||
struct Blur_Previews: PreviewProvider {
|
||||
struct Preview: View {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ public extension AnyTransition.MovingParts {
|
|||
}
|
||||
}
|
||||
|
||||
internal struct Boing: Animatable, GeometryEffect {
|
||||
internal struct Boing: DebugProgressableAnimation, GeometryEffect {
|
||||
var edge: Edge
|
||||
|
||||
var animatableData: CGFloat = 0
|
||||
|
|
@ -107,6 +107,12 @@ internal struct Boing: Animatable, GeometryEffect {
|
|||
}
|
||||
|
||||
#if os(iOS) && DEBUG
|
||||
struct Boing_Preview: PreviewableAnimation, PreviewProvider {
|
||||
static var animation: Scaled<Boing> {
|
||||
Scaled(Boing(.top, animatableData: 0))
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 15.0, *)
|
||||
struct Bounce_Previews: PreviewProvider {
|
||||
struct Item: Identifiable {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@ public extension AnyTransition.MovingParts {
|
|||
}
|
||||
}
|
||||
|
||||
internal struct Clock: ViewModifier, Animatable, AnimatableModifier {
|
||||
internal struct Clock: ViewModifier, DebugProgressableAnimation, AnimatableModifier {
|
||||
|
||||
var origin: UnitPoint
|
||||
|
||||
var animatableData: AnimatablePair<CGFloat, CGFloat>
|
||||
|
|
@ -32,7 +33,8 @@ internal struct Clock: ViewModifier, Animatable, AnimatableModifier {
|
|||
}
|
||||
|
||||
var progress: CGFloat {
|
||||
animatableData.first
|
||||
get { animatableData.first }
|
||||
set { animatableData.first = newValue }
|
||||
}
|
||||
|
||||
var blurRadius: CGFloat {
|
||||
|
|
@ -84,6 +86,12 @@ internal struct Clock: ViewModifier, Animatable, AnimatableModifier {
|
|||
}
|
||||
|
||||
#if os(iOS) && DEBUG
|
||||
struct Clock_Preview: PreviewableAnimation, PreviewProvider {
|
||||
static var animation: Clock {
|
||||
Clock(origin: .center, blurRadius: 0, progress: 0)
|
||||
}
|
||||
}
|
||||
|
||||
struct Clock_Previews: PreviewProvider {
|
||||
struct Item: Identifiable {
|
||||
var color: Color
|
||||
|
|
|
|||
|
|
@ -20,14 +20,9 @@ public extension AnyTransition.MovingParts {
|
|||
}
|
||||
}
|
||||
|
||||
internal struct Snapshot: ViewModifier, Animatable, AnimatableModifier, Hashable {
|
||||
internal struct Snapshot: ViewModifier, ProgressableAnimation, AnimatableModifier, Hashable {
|
||||
var animatableData: CGFloat = 0
|
||||
|
||||
var progress: CGFloat {
|
||||
get { animatableData }
|
||||
set { animatableData = newValue }
|
||||
}
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
content
|
||||
.saturation(0.5 + 0.5 * clamp(progress))
|
||||
|
|
@ -38,14 +33,9 @@ internal struct Snapshot: ViewModifier, Animatable, AnimatableModifier, Hashable
|
|||
}
|
||||
}
|
||||
|
||||
internal struct ExposureFade: ViewModifier, Animatable, AnimatableModifier, Hashable {
|
||||
internal struct ExposureFade: ViewModifier, ProgressableAnimation, AnimatableModifier, Hashable {
|
||||
var animatableData: CGFloat = 0
|
||||
|
||||
var progress: CGFloat {
|
||||
get { animatableData }
|
||||
set { animatableData = newValue }
|
||||
}
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
content
|
||||
.opacity(Double(1.0 - pow(2.0, -10.0 * progress)))
|
||||
|
|
@ -55,6 +45,18 @@ internal struct ExposureFade: ViewModifier, Animatable, AnimatableModifier, Hash
|
|||
}
|
||||
|
||||
#if os(iOS) && DEBUG
|
||||
struct Snapshot_Preview: PreviewableAnimation, PreviewProvider {
|
||||
static var animation: Snapshot {
|
||||
Snapshot(animatableData: 0)
|
||||
}
|
||||
}
|
||||
|
||||
struct FilmExposure_Preview: PreviewableAnimation, PreviewProvider {
|
||||
static var animation: ExposureFade {
|
||||
ExposureFade(animatableData: 0)
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 15.0, *)
|
||||
struct ExoposureFade_Previews: PreviewProvider {
|
||||
struct Preview: View {
|
||||
|
|
|
|||
|
|
@ -21,16 +21,11 @@ public extension AnyTransition.MovingParts {
|
|||
}
|
||||
}
|
||||
|
||||
internal struct Flicker: ViewModifier, Animatable, AnimatableModifier, Hashable {
|
||||
internal struct Flicker: ViewModifier, ProgressableAnimation, AnimatableModifier, Hashable {
|
||||
var count: Int
|
||||
|
||||
var animatableData: CGFloat
|
||||
|
||||
private var progress: CGFloat {
|
||||
get { animatableData }
|
||||
set { animatableData = newValue }
|
||||
}
|
||||
|
||||
private var isVisible: Bool {
|
||||
(progress * CGFloat(count)).remainder(dividingBy: 1) >= 0
|
||||
}
|
||||
|
|
@ -43,6 +38,12 @@ internal struct Flicker: ViewModifier, Animatable, AnimatableModifier, Hashable
|
|||
}
|
||||
|
||||
#if os(iOS) && DEBUG
|
||||
struct Flicker_Preview: PreviewableAnimation, PreviewProvider {
|
||||
static var animation: Flicker {
|
||||
Flicker(count: 1, animatableData: 0)
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 15.0, *)
|
||||
struct Flicker_Previews: PreviewProvider {
|
||||
struct Preview: View {
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ public extension AnyTransition.MovingParts {
|
|||
}
|
||||
}
|
||||
|
||||
internal struct Glare: ViewModifier, Animatable, AnimatableModifier {
|
||||
internal struct Glare: ViewModifier, DebugProgressableAnimation, AnimatableModifier {
|
||||
var animatableData: CGFloat = 0
|
||||
|
||||
var angle: Angle
|
||||
|
|
@ -132,8 +132,37 @@ internal struct Glare: ViewModifier, Animatable, AnimatableModifier {
|
|||
}
|
||||
|
||||
#if os(iOS) && DEBUG
|
||||
@available(iOS 16.0, *)
|
||||
struct Glare_Preview: PreviewableAnimation, PreviewProvider {
|
||||
static var animation: Glare {
|
||||
Glare(.degrees(45), color: .white, increasedBrightness: true, animatableData: 0)
|
||||
}
|
||||
|
||||
static var content: any View {
|
||||
Glare_Previews.makeRect(start: .indigo, end: .purple)
|
||||
.frame(width: 100, height: 100)
|
||||
.preferredColorScheme(.dark)
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 16.0, *)
|
||||
struct Glare_Previews: PreviewProvider {
|
||||
static func makeRect(start: Color, end: Color) -> some View {
|
||||
RoundedRectangle(cornerRadius: 18, style: .continuous)
|
||||
.fill(LinearGradient(
|
||||
colors: [start, end],
|
||||
startPoint: .topLeading,
|
||||
endPoint: .bottom
|
||||
))
|
||||
.compositingGroup()
|
||||
.overlay {
|
||||
Text("Hello\nWorld")
|
||||
.foregroundStyle(.white.shadow(.inner(radius: 0.5)))
|
||||
}
|
||||
.font(.system(.largeTitle, design: .rounded).weight(.medium))
|
||||
.multilineTextAlignment(.center)
|
||||
}
|
||||
|
||||
struct Item: Identifiable {
|
||||
var color1: Color
|
||||
var color2: Color
|
||||
|
|
@ -214,19 +243,7 @@ struct Glare_Previews: PreviewProvider {
|
|||
ForEach(items.indices, id: \.self) { index in
|
||||
let item = items[index]
|
||||
|
||||
RoundedRectangle(cornerRadius: 18, style: .continuous)
|
||||
.fill(LinearGradient(
|
||||
colors: [item.color1, item.color2],
|
||||
startPoint: .topLeading,
|
||||
endPoint: .bottom
|
||||
))
|
||||
.compositingGroup()
|
||||
.overlay {
|
||||
Text("Hello\nWorld")
|
||||
.foregroundStyle(.white.shadow(.inner(radius: 0.5)))
|
||||
}
|
||||
.font(.system(.largeTitle, design: .rounded).weight(.medium))
|
||||
.multilineTextAlignment(.center)
|
||||
Glare_Previews.makeRect(start: item.color1, end: item.color2)
|
||||
.transition(
|
||||
.asymmetric(
|
||||
insertion: .movingParts.glare(angle: angle),
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ public extension AnyTransition.MovingParts {
|
|||
}
|
||||
}
|
||||
|
||||
private struct Iris: ViewModifier, Animatable, AnimatableModifier {
|
||||
struct Iris: ViewModifier, DebugProgressableAnimation, AnimatableModifier {
|
||||
var origin: UnitPoint
|
||||
|
||||
var blurRadius: CGFloat
|
||||
|
|
@ -58,6 +58,12 @@ private struct Iris: ViewModifier, Animatable, AnimatableModifier {
|
|||
}
|
||||
|
||||
#if os(iOS) && DEBUG
|
||||
struct Iris_Preview: PreviewableAnimation, PreviewProvider {
|
||||
static var animation: Iris {
|
||||
Iris(origin: .center, animatableData: 0)
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 15.0, *)
|
||||
struct Mask_Previews: PreviewProvider {
|
||||
struct Preview: View {
|
||||
|
|
|
|||
|
|
@ -16,18 +16,13 @@ public extension AnyTransition.MovingParts {
|
|||
}
|
||||
}
|
||||
|
||||
private struct Poof: ViewModifier, Animatable, AnimatableModifier {
|
||||
struct Poof: ViewModifier, ProgressableAnimation, AnimatableModifier {
|
||||
var animatableData: CGFloat = 0
|
||||
|
||||
internal init(animatableData: CGFloat) {
|
||||
self.animatableData = animatableData
|
||||
}
|
||||
|
||||
var progress: CGFloat {
|
||||
get { animatableData }
|
||||
set { animatableData = newValue }
|
||||
}
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
let frame = (6 * progress).rounded()
|
||||
|
||||
|
|
@ -56,6 +51,25 @@ private struct Poof: ViewModifier, Animatable, AnimatableModifier {
|
|||
}
|
||||
|
||||
#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 {
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ public extension AnyTransition.MovingParts {
|
|||
}
|
||||
|
||||
@available(iOS 15.0, *)
|
||||
private struct Pop: AnimatableModifier, Animatable, ViewModifier {
|
||||
struct Pop: AnimatableModifier, ProgressableAnimation, ViewModifier {
|
||||
var animatableData: CGFloat = 0
|
||||
|
||||
var style: AnyShapeStyle
|
||||
|
|
@ -63,11 +63,6 @@ private struct Pop: AnimatableModifier, Animatable, ViewModifier {
|
|||
self.style = style
|
||||
}
|
||||
|
||||
var progress: CGFloat {
|
||||
get { animatableData }
|
||||
set { animatableData = newValue }
|
||||
}
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
let t = clamp(2 * (progress - 1/2.5))
|
||||
|
||||
|
|
@ -170,6 +165,19 @@ private struct Pop: AnimatableModifier, Animatable, ViewModifier {
|
|||
}
|
||||
|
||||
#if os(iOS) && DEBUG
|
||||
struct Pop_Preview: PreviewableAnimation, PreviewProvider {
|
||||
static var animation: Pop {
|
||||
Pop(style: AnyShapeStyle(.tint), animatableData: 0)
|
||||
}
|
||||
|
||||
static var content: any View {
|
||||
Image(systemName: "heart.fill")
|
||||
.foregroundColor(.red)
|
||||
.tint(.red)
|
||||
.preferredColorScheme(.dark)
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 15.0, *)
|
||||
struct Pop_Previews: PreviewProvider {
|
||||
struct Preview: View {
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ public extension AnyTransition.MovingParts {
|
|||
}
|
||||
}
|
||||
|
||||
internal struct Skid: Animatable, GeometryEffect {
|
||||
internal struct Skid: DebugProgressableAnimation, GeometryEffect {
|
||||
var direction: AnyTransition.MovingParts.SkidDirection
|
||||
|
||||
var animatableData: CGFloat = 0
|
||||
|
|
@ -73,6 +73,29 @@ internal struct Skid: Animatable, GeometryEffect {
|
|||
}
|
||||
|
||||
#if os(iOS) && DEBUG
|
||||
struct Skid_Preview: PreviewableAnimation, PreviewProvider {
|
||||
static var animation: Skid {
|
||||
Skid(.leading)
|
||||
}
|
||||
|
||||
static var content: some View {
|
||||
RoundedRectangle(cornerRadius: 8, style: .continuous)
|
||||
.fill(Color.orange)
|
||||
.overlay {
|
||||
Text("Jell-O\nWorld")
|
||||
.blendMode(.difference)
|
||||
.offset(x: 2, y: 2)
|
||||
}
|
||||
.compositingGroup()
|
||||
.overlay {
|
||||
Text("Jell-O\nWorld")
|
||||
}
|
||||
.font(.system(.headline, design: .rounded).weight(.black))
|
||||
.multilineTextAlignment(.center)
|
||||
.frame(width: 150, height: 150)
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 15.0, *)
|
||||
struct Skid_Previews: PreviewProvider {
|
||||
struct Item: Identifiable {
|
||||
|
|
|
|||
Loading…
Reference in a new issue