SwiftUI 可动画渐变

一系列用于创建动画颜色渐变的 SwiftUI View Modifier。

CI Status Twitter: @cypher_poet

特性

要求

安装

可以通过 Swift Package Manager 使用 AnimatableGradients。您可以将其作为依赖项添加到您的 Package.swift 文件中

let package = Package(
    //...
    dependencies: [
        .package(url: "https://github.com/CypherPoet/AnimatableGradients", from: "0.1.1"),
    ],
    //...
)

然后,在您想要使用它的任何地方简单地 import AnimatableGradients

用法

AnimatableGradients 公开的 view modifier 都遵循其 AnimatableGradientModifier 协议。(您可以在此处查看实现。)

AnimatableGradientModifier 协议
protocol AnimatableGradientModifier: AnimatableModifier {
    associatedtype BaseShape: Shape
    associatedtype GradientShapeStyle: ShapeStyle

    var baseShape: BaseShape { get }
    var startColors: [UIColor] { get }
    var endColors: [UIColor] { get }

    var completionPercentage: CGFloat { get set }

    func gradientFill(in geometry: GeometryProxy) -> GradientShapeStyle
}

为了使用这些 modifier,AnimatableGradients 提供了以下在 ViewShape 上的扩展

(更详细的说明可以在下面找到。)

🔑 为了实现动画,您的包含视图需要使用一个绑定到 CGFloat 状态值的上述 modifier,该值的范围在 0.0 和 1.0 之间。

@State private var animationCompletion: CGFloat = 0.0

这是“动画完成”百分比,每个 AnimatableGradientModifier 将使用它来在每个渲染帧期间生成插值颜色值。

此外,相同的包含视图需要动画化动画完成的更改。一个常见的模式包括从包含视图的 onAppear modifier 重复动画该值,以创建连续的动画效果。

.onAppear {
    withAnimation(
        Animation.easeInOut(duration: 1.0).repeatForever(autoreverses: true)
    ) {
        self.animationCompletion = 1.0
    }
}

总而言之,一个最小的功能示例可能如下所示

struct ContentView {
    @State private var animationCompletion: CGFloat = 0.0

    var body: some View {
        RoundedRectangle(cornerRadius: 24)
            .animatableLinearGradient(
                startColors: [.red, .blue],
                endColors: [.green, .yellow],
                completionPercentage: animationCompletion
            )
            .onAppear {
                withAnimation(
                    Animation.easeInOut(duration: 1.0).repeatForever(autoreverses: true)
                ) {
                    self.animationCompletion = 1.0
                }
            }
    }
}

现在是一些更详细的信息...

可动画线性渐变

在 Shape 上的用法

extension Shape {

    public func animatableLinearGradient (
        startColors: [UIColor],
        endColors: [UIColor],
        startPoint: UnitPoint = .topLeading,
        endPoint: UnitPoint = .bottomTrailing,
        completionPercentage: CGFloat
    ) -> some View {
      ...
    }
}
你正在使用 👆

RoundedRectangle(cornerRadius: 24)
    .animatableLinearGradient(
        startColors: [.systemPurple, .systemBlue, .systemGreen, .white],
        endColors: [.systemGray, .systemPink, .systemOrange, .systemRed],
        completionPercentage: animationCompletion
    )
你可能如何使用它 👆

在 View 上的用法

extension View {

    public func animatableLinearGradient<BaseShape: Shape>(
        baseShape: BaseShape,
        startColors: [UIColor],
        endColors: [UIColor],
        startPoint: UnitPoint = .topLeading,
        endPoint: UnitPoint = .bottomTrailing,
        completionPercentage: CGFloat
    ) -> some View {
      ...
    }
}
你正在使用 👆

Color.clear
    .animatableLinearGradient(
            baseShape: RoundedRectangle(cornerRadius: 24),
            startColors: [.systemPurple, .systemBlue, .systemGreen, .white],
            endColors: [.systemGray, .systemPink, .systemOrange, .systemRed],
            completionPercentage: animationCompletion
    )
你可能如何使用它 👆

📸 示例

可动画径向渐变

在 Shape 上的用法

extension Shape {

   public func animatableRadialGradient (
        startColors: [UIColor],
        endColors: [UIColor],
        centerPoint: UnitPoint = .center,
        startRadius: CGFloat? = nil,
        endRadius: CGFloat? = nil,
        completionPercentage: CGFloat
    ) -> some View {
        ...
    }
}
你正在使用 👆

RoundedRectangle(cornerRadius: 24)
    .animatableRadialGradient(
        startColors: [.systemPurple, .systemBlue, .systemGreen, .white],
        endColors: [.systemGray, .systemPink, .systemOrange, .black],
        completionPercentage: animationCompletion
    )
你可能如何使用它 👆

在 View 上的用法

extension View {

    public func animatableRadialGradient<BaseShape: Shape>(
        baseShape: BaseShape,
        startColors: [UIColor],
        endColors: [UIColor],
        centerPoint: UnitPoint = .center,
        startRadius: CGFloat? = nil,
        endRadius: CGFloat? = nil,
        completionPercentage: CGFloat
    ) -> some View {
        ...
    }
}
你正在使用 👆

Color.clear
    .animatableRadialGradient(
        baseShape: RoundedRectangle(cornerRadius: 24),
        startColors: [.systemPurple, .systemBlue, .systemGreen, .white],
        endColors: [.systemGray, .systemPink, .systemOrange, .black],
        completionPercentage: animationCompletion
    )
你可能如何使用它 👆

📸 示例

可动画角度渐变

在 Shape 上的用法

extension Shape {

    /// - Parameters:
    ///   - fullSpanStartAngle: Setting this property will cause the gradient to being at
    ///         the specified offset, and then span the entire circumference. (Default: `nil`)
    public func animatableAngularGradient (
        startColors: [UIColor],
        endColors: [UIColor],
        centerPoint: UnitPoint = .center,
        fullSpanStartAngle: Angle,
        completionPercentage: CGFloat
    ) -> some View {
        ...
    }


    public func animatableAngularGradient (
        startColors: [UIColor],
        endColors: [UIColor],
        centerPoint: UnitPoint = .center,
        startAngle: Angle = .zero,
        endAngle: Angle = .radians(2 * .pi),
        completionPercentage: CGFloat
    ) -> some View {
        ...
    }
}
你正在使用 👆

RoundedRectangle(cornerRadius: 24)
    .animatableAngularGradient(
        startColors: [.systemPurple, .systemBlue, .systemGreen, .white],
        endColors: [.systemGray, .systemPink, .systemOrange, .systemRed],
        completionPercentage: animationCompletion
    )
你可能如何使用它 👆

在 View 上的用法

extension View {

    /// - Parameters:
    ///   - fullSpanStartAngle: Setting this property will cause the gradient to being at
    ///         the specified offset, and then span the entire circumference. (Default: `nil`)
    public func animatableAngularGradient<BaseShape: Shape>(
        baseShape: BaseShape,
        startColors: [UIColor],
        endColors: [UIColor],
        centerPoint: UnitPoint = .center,
        fullSpanStartAngle: Angle,
        completionPercentage: CGFloat
    ) -> some View {
        ...
    }


    public func animatableAngularGradient<BaseShape: Shape>(
        baseShape: BaseShape,
        startColors: [UIColor],
        endColors: [UIColor],
        centerPoint: UnitPoint = .center,
        startAngle: Angle = .zero,
        endAngle: Angle = .radians(2 * .pi),
        completionPercentage: CGFloat
    ) -> some View {
        ...
    }
}
你正在使用 👆

Color.clear
    .animatableAngularGradient(
        baseShape: RoundedRectangle(cornerRadius: 24),
        startColors: [.systemPurple, .systemBlue, .systemGreen, .white],
        endColors: [.systemGray, .systemPink, .systemOrange, .systemRed],
        completionPercentage: animationCompletion
    )
你可能如何使用它 👆

📸 示例

⚠️边缘情况

贡献

非常欢迎对 AnimatableGradients 做出贡献。查看一些问题模板以获取更多信息。

路线图

许可证

AnimatableGradients 在 MIT 许可下可用。 有关更多信息,请参见LICENSE 文件