mirror of
https://github.com/fxm90/GradientLoadingBar.git
synced 2026-06-16 12:24:31 +00:00
70 lines
2.4 KiB
Swift
70 lines
2.4 KiB
Swift
//
|
|
// GradientLoadingBarView.swift
|
|
// GradientLoadingBar
|
|
//
|
|
// Created by Felix Mau on 08.03.22.
|
|
// Copyright © 2022 Felix Mau. All rights reserved.
|
|
//
|
|
|
|
import SwiftUI
|
|
|
|
@available(iOS 13.0, *)
|
|
public struct GradientLoadingBarView: View {
|
|
// MARK: - Config
|
|
|
|
public enum Config {
|
|
/// The default color palette for the gradient colors.
|
|
public static let gradientColors = UIColor.GradientLoadingBar.gradientColors.map(Color.init)
|
|
|
|
/// The default duration for the progress animation, measured in seconds.
|
|
public static let progressDuration = TimeInterval.GradientLoadingBar.progressDuration
|
|
}
|
|
|
|
// MARK: - Private properties
|
|
|
|
private let gradientColors: [Color]
|
|
private let progressAnimation: Animation
|
|
|
|
@State
|
|
private var offset: CGFloat = 0
|
|
|
|
// MARK: - Initializer
|
|
|
|
public init(gradientColors: [Color] = Config.gradientColors,
|
|
progressDuration: TimeInterval = Config.progressDuration) {
|
|
// E.g. for array of [.red, .yellow, .green]
|
|
// we will create [.red, .yellow, .green, .yellow, .red, .yellow, .green]
|
|
//
|
|
// E.g. for array of [.red, .yellow, .green, .blue]
|
|
// we will create [.red, .yellow, .green, .blue, .green, .yellow, .red, .yellow, .green, .blue]
|
|
var reversedGradientColors = Array(gradientColors.reversed())
|
|
reversedGradientColors.removeFirst()
|
|
reversedGradientColors.removeLast()
|
|
|
|
self.gradientColors = gradientColors + reversedGradientColors + gradientColors
|
|
|
|
progressAnimation = .linear(duration: progressDuration).repeatForever(autoreverses: false)
|
|
}
|
|
|
|
// MARK: - Render
|
|
|
|
public var body: some View {
|
|
GeometryReader { proxy in
|
|
LinearGradient(colors: gradientColors, startPoint: .leading, endPoint: .trailing)
|
|
// To fit `gradientColors + reversedGradientColors + gradientColors` in our view,
|
|
// we have to apply three times the width of our parent view.
|
|
.frame(width: proxy.size.width * 3)
|
|
.offset(x: offset, y: 0)
|
|
.onAppear {
|
|
// We want to animate from left to right.
|
|
// Therefore we start with the negative offset, and afterwards animate to an offset of zero.
|
|
offset = proxy.size.width * -2
|
|
|
|
withAnimation(progressAnimation) {
|
|
offset = 0
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|