diff --git a/Sources/FabulaItemsProvider/Contributor.swift b/Sources/FabulaItemsProvider/Contributor.swift index 54aec57..95de55e 100644 --- a/Sources/FabulaItemsProvider/Contributor.swift +++ b/Sources/FabulaItemsProvider/Contributor.swift @@ -17,7 +17,8 @@ public struct Contributor { Contributor.soccer01, Contributor.tgeisse, Contributor.henry, - Contributor.regi93 + Contributor.regi93, + Contributor.onaxiz ] public static let jasu = ContributorData(name: "jasu", location: "Korea", email: "jasudev@gmail.com", link: "https://github.com/jasudev", imageName: "jasu") @@ -25,4 +26,5 @@ public struct Contributor { public static let tgeisse = ContributorData(name: "tgeisse", location: "United States", email: nil, link: "https://github.com/tgeisse", imageName: nil) public static let henry = ContributorData(name: "henry", location: "Korea", email: "wcbe9745@naver.com", link: "https://github.com/lemona-97", imageName: nil) public static let regi93 = ContributorData(name: "regi93", location: "Korea", email: "hellgey777@naver.com", link: "https://github.com/regi93", imageName: nil) + public static let onaxiz = ContributorData(name: "onaxiz", location: "Russia", email: "maksimovaswift@gmail.com", link: "https://github.com/onaxiz", imageName: nil) } diff --git a/Sources/FabulaItemsProvider/Items/P287_EtherealGlow.swift b/Sources/FabulaItemsProvider/Items/P287_EtherealGlow.swift new file mode 100644 index 0000000..4cd07cc --- /dev/null +++ b/Sources/FabulaItemsProvider/Items/P287_EtherealGlow.swift @@ -0,0 +1,150 @@ +// +// P287_EtherealGlow.swift +// FabulaItemsProvider +// +// Soft ethereal glows for background +// + +import SwiftUI + +public struct P287_EtherealGlow: View { + + public init() {} + + public var body: some View { + ZStack { + Color.fabulaBack0 + .ignoresSafeArea() + + EtherealGlowView() + } + } +} + +fileprivate struct EtherealGlowView: View { + + @State private var phase: CGFloat = 0 + @State private var phase2: CGFloat = 0 + @State private var phase3: CGFloat = 0 + @State private var phase4: CGFloat = 0 + @State private var phase5: CGFloat = 0 + + var body: some View { + GeometryReader { geometry in + let w = geometry.size.width + let h = geometry.size.height + + ZStack { + GlowOrb( + phase: phase, + scalePhase: phase * 0.5, + baseX: w * 0.25, + baseY: h * 0.35, + size: w * 0.9, + color: Color.fabulaSecondary, + drift: 0.18 + ) + + GlowOrb( + phase: phase2, + scalePhase: phase2 * 0.6, + baseX: w * 0.7, + baseY: h * 0.45, + size: w * 0.75, + color: Color.fabulaPrimary, + drift: 0.15 + ) + + GlowOrb( + phase: phase3, + scalePhase: phase3 * 0.4, + baseX: w * 0.5, + baseY: h * 0.55, + size: w * 0.7, + color: Color.fabulaSecondary, + drift: 0.2 + ) + + GlowOrb( + phase: phase4, + scalePhase: phase4 * 0.55, + baseX: w * 0.35, + baseY: h * 0.5, + size: w * 0.5, + color: Color.fabulaPrimary.opacity(0.8), + drift: 0.22 + ) + + GlowOrb( + phase: phase5, + scalePhase: phase5 * 0.45, + baseX: w * 0.65, + baseY: h * 0.4, + size: w * 0.55, + color: Color.fabulaSecondary.opacity(0.8), + drift: 0.16 + ) + } + .blendMode(.screen) + .blur(radius: 40) + .onAppear { + withAnimation(.easeInOut(duration: 6).repeatForever(autoreverses: true)) { + phase = .pi * 2 + } + withAnimation(.easeInOut(duration: 7).repeatForever(autoreverses: true).delay(0.3)) { + phase2 = .pi * 2 + } + withAnimation(.easeInOut(duration: 5.5).repeatForever(autoreverses: true).delay(0.6)) { + phase3 = .pi * 2 + } + withAnimation(.easeInOut(duration: 6.5).repeatForever(autoreverses: true).delay(1)) { + phase4 = .pi * 2 + } + withAnimation(.easeInOut(duration: 7.5).repeatForever(autoreverses: true).delay(1.3)) { + phase5 = .pi * 2 + } + } + } + } +} + +fileprivate struct GlowOrb: View { + var phase: CGFloat + var scalePhase: CGFloat + let baseX: CGFloat + let baseY: CGFloat + let size: CGFloat + let color: Color + let drift: CGFloat + + var body: some View { + Ellipse() + .fill( + RadialGradient( + colors: [ + color.opacity(0.6), + color.opacity(0.3), + color.opacity(0.1), + color.opacity(0) + ], + center: .center, + startRadius: 0, + endRadius: size * 0.55 + ) + ) + .frame(width: size, height: size * 1.5) + .scaleEffect(0.85 + 0.15 * sin(scalePhase)) + .offset( + x: cos(phase) * size * drift, + y: sin(phase * 0.7) * size * drift + ) + .position(x: baseX, y: baseY) + } +} + +struct P287_EtherealGlow_Previews: PreviewProvider { + static var previews: some View { + P287_EtherealGlow() + .preferredColorScheme(.dark) + } +} diff --git a/Sources/FabulaItemsProvider/ItemsProvider.swift b/Sources/FabulaItemsProvider/ItemsProvider.swift index 334791b..cba40d2 100644 --- a/Sources/FabulaItemsProvider/ItemsProvider.swift +++ b/Sources/FabulaItemsProvider/ItemsProvider.swift @@ -27,7 +27,16 @@ public class ItemsProvider { public init() {} public var items: [ItemData] { - [ ItemData(id: 286, category: .study, + [ + ItemData(id: 287, category: .uiux, + section: "Animation", + createDate: "2025-02-10", + title: "Ethereal Glow", + caption: "Soft glowing orbs with organic flow using Fabula color palette", + creator: Contributor.onaxiz.name, + tags: "glow, gradient, animation, fabula, ethereal", + view: FAnyView(P287_EtherealGlow())), + ItemData(id: 286, category: .study, section: "Animation", createDate: "2025-07-20", title: "Parallax Poster",