LinearGradient 偏移动画在 SwiftUI 中不起作用

问题描述 投票:0回答:1

我试图通过动画它的

Text
位置来使用
LinearGradient
逐行显示一块
offset(y:)
块,但它似乎不起作用。这是我所拥有的:

struct GradientView: View {
    @State var animateBlur = false
    @State var isVisible: Bool = false
    let text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. "
    
    var body: some View {
        VStack {
            GroupBox {
                Toggle("Visible", isOn: $isVisible.animation())
            }

            if isVisible {
                Text(text)
                    .font(.title2)
                    .bold()
                    .overlay {
                        GeometryReader { proxy in
//                            Color.red // << works
                            LinearGradient(colors: [.clear, .white], startPoint: .top, endPoint: .bottom) // << does not work
                                .frame(height: proxy.size.height)
                                .offset(y: animateBlur ? proxy.size.height : 0)
                                .animation(.easeInOut(duration: 1), value: animateBlur)
                                .onAppear {
                                    animateBlur.toggle()
                                }
                                
                        }
                    }
                    .clipShape(Rectangle())
            }
            Spacer()
        }
        .onChange(of: isVisible, {
            if isVisible == false { animateBlur = false }
        })
        .padding()
    }
}

目前有几个问题。

  1. 它似乎适用于
    Color
    ,但不适用于
    LinearGradient
    。动画运行后,我仍然看到
    LinearGradient
    覆盖在文本的下半部分。我希望
    LinearGradient
    在垂直方向上以动画方式显示出完整的文本块。
  2. 仅使用
    [.clear, .white]
    作为渐变颜色,考虑到文本的高度和渐变颜色以50-50的比例分布,它显示的不仅仅是一行。我可以更新颜色以拥有更多
    whites
    [.clear, .white, .white, .white, .white, .white]
    ,使得透明部分收缩到渐变的顶部,但这是不可行的。我也尝试使用梯度停止,像这样
    LinearGradient(stops: [.init(color: .clear, location: 0.1), .init(color: .white, location: 0.9)]
    ,但它没有产生预期的结果。

如有任何帮助,我们将不胜感激。

ios animation swiftui
1个回答
0
投票

如果您希望看到不透明度被漫反射边缘擦除,则可以通过动画渐变的起点和终点来实现。无需应用 y 偏移。

起点和终点不必限制在0-1范围内。渐变的可见部分确实是这个范围,但如果终点是 2 而不是 1,那么渐变将从 0-2 拉伸,你只会看到一半的渐变。

下面的版本使用了分为 3 个区域的渐变:

  • 前三分之一很清楚
  • 中间三分之一是渐变,从透明到白色
  • 最后三分之一是白色。

当在

.onAppear
中设置标志时,起点和终点用于将渐变的可见部分从最后三分之一移动到前三分之一。我发现叠加后还需要应用
.compositingGroup()
,否则初始显示时会闪烁。

struct GradientView: View {
    @State private var isVisible = false
    @State private var animateBlur = false
    let text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. "

    var body: some View {
        VStack {
            GroupBox {
                Toggle("Visible", isOn: $isVisible.animation())
            }
            if isVisible {
                Text(text)
                    .font(.title2)
                    .bold()
                    .overlay {
                        LinearGradient(
                            colors: [.clear, .clear, .white, .white],
                            startPoint: UnitPoint(x: 0.5, y: animateBlur ? 0 : -2),
                            endPoint: UnitPoint(x: 0.5, y: animateBlur ? 3 : 1)
                        )
                        .animation(.easeInOut(duration: 2), value: animateBlur)
                        .onAppear { animateBlur = true }
                        .onDisappear { animateBlur = false }
                    }
                    .compositingGroup()
            }
            Spacer()
        }
        .padding()
    }
}

Animation

© www.soinside.com 2019 - 2024. All rights reserved.