SwiftUI: Как использовать линейный градиент в индикаторе выполнения?

#ios #swift #swiftui #gradient #linear-gradients

Вопрос:

Я пытаюсь построить представление, представляющее собой закругленный прямоугольник на гистограмме, с градиентом, который становится темнее, чем выше value (значение по шкале 0-10,0). Но я, кажется, не могу понять, как использовать UnitPoint здесь конечную точку, чтобы получить правильную точку, где должен заканчиваться градиент. Другими словами, если значение = 5,0, я хочу, чтобы градиент отображал верхнюю часть полосы на полпути к самому темному цвету градиента, или, другими словами, самый темный цвет градиента всегда равен 10,0, и цвет полосы будет отображаться только на уровне полосы.

 var body: some View {
    VStack {
        RoundedRectangle(cornerRadius: 5.0)
            .fill(LinearGradient(gradient: Gradient(colors: [ Color(UIColor(red: 0.98, green: 0.85, blue: 0.38, alpha: 1.00)) , Color(UIColor(red: 0.63, green: 0.02, blue: 0.11, alpha: 1.00))]), startPoint: .bottom, endPoint: UnitPoint(x: 0.5, y: CGFloat((value * 10 / 100)))))
            .frame(width: 40, height: open ? CGFloat(value * 10) : 0)
    }
    
}
 

Ответ №1:

Я думаю, что вам лучше всего «замаскировать» градиент, а не пытаться вычислить endPoint его .

Вот пример с 5 «барами» в an HStack — первый бар имеет максимальное значение 10 , затем значения баров идут 9, 7.5, 5, 2 :

введите описание изображения здесь

Пример кода:

 import SwiftUI

struct GradBars: View {
    
    var maxValue: CGFloat = 10
    
    var val1: CGFloat = 10
    var val2: CGFloat = 9
    var val3: CGFloat = 7.5
    var val4: CGFloat = 5
    var val5: CGFloat = 2
    
    @State var open: Bool = true

    let gradient = LinearGradient(gradient: Gradient(colors: [ Color(UIColor(red: 0.98, green: 0.85, blue: 0.38, alpha: 1.00)) ,
                                                               Color(UIColor(red: 0.63, green: 0.02, blue: 0.11, alpha: 1.00))]),
                                  startPoint: .bottom,
                                  endPoint: .top)
    
    var body: some View {
        VStack {
            HStack(alignment: .bottom, spacing: 8, content: {

                Rectangle()
                    .fill(gradient)
                    .frame(width: 40, height: open ? maxValue * 10 : 0, alignment: .bottom)
                    .mask(
                        VStack {
                            RoundedRectangle(cornerRadius: 5.0).frame(height: val1 * 10)
                        }.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottom)
                    )
                
                Rectangle()
                    .fill(gradient)
                    .frame(width: 40, height: open ? maxValue * 10 : 0, alignment: .bottom)
                    .mask(
                        VStack {
                            RoundedRectangle(cornerRadius: 5.0).frame(height: val2 * 10)
                        }.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottom)
                    )
                
                Rectangle()
                    .fill(gradient)
                    .frame(width: 40, height: open ? maxValue * 10 : 0, alignment: .bottom)
                    .mask(
                        VStack {
                            RoundedRectangle(cornerRadius: 5.0).frame(height: val3 * 10)
                        }.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottom)
                    )
                
                Rectangle()
                    .fill(gradient)
                    .frame(width: 40, height: open ? maxValue * 10 : 0, alignment: .bottom)
                    .mask(
                        VStack {
                            RoundedRectangle(cornerRadius: 5.0).frame(height: val4 * 10)
                        }.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottom)
                    )
                
                Rectangle()
                    .fill(gradient)
                    .frame(width: 40, height: open ? maxValue * 10 : 0, alignment: .bottom)
                    .mask(
                        VStack {
                            RoundedRectangle(cornerRadius: 5.0).frame(height: val5 * 10)
                        }.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottom)
                    )
                
            })
        }
    }

}

struct GradBars_Previews: PreviewProvider {
    static var previews: some View {
        GradBars()
    }
}