Home > database >  Why does my code produce an unexpected result when animating a saturation change
Why does my code produce an unexpected result when animating a saturation change

Time:11-03

I've been learning paths shapes and more and tried to practice by making a rectangle with lots of animation possibility. The results i achieved were very unexpected(to me). The gradients that i used just weird out at every animation

i've tried seeing if any values changed unexpectedly but to no avail. heres the code that has this problem:

import SwiftUI

struct ColorCyclingCircle: View, Animatable {
    var amount = 0.0
    var steps = 100.0
    
    var saturation = 1.0
    var brightness1 = 1.0
    var brightness2 = 0.5
    
    var animatableData: AnimatablePair<AnimatablePair<Double, Double>, Double> {
        get { AnimatablePair(AnimatablePair(steps, amount), saturation) }
        set {
            steps = newValue.first.first
            amount = newValue.first.first
            saturation = newValue.second
        }
    }
    
    var body: some View {
        ZStack {
            ForEach(0..<Int(steps), id: \.self) { value in
                Rectangle()
                    .inset(by: Double(value))
                    .strokeBorder(
                        LinearGradient(
                            gradient: Gradient(colors: [
                                color(for: value, brightness: brightness1),
                                color(for: value, brightness: brightness2)
                            ]),
                            startPoint: .top,
                            endPoint: .bottom
                        ),
                        lineWidth: 2
                    )
            }
        }
        .drawingGroup()
    }

    func color(for value: Int, brightness: Double) -> Color {
        var targetHue = Double(value) / Double(steps)   amount

        if targetHue > 1 {
            targetHue -= 1
        }

        return Color(hue: targetHue, saturation: saturation, brightness: brightness)
    }
}

struct ContentView: View {
    @State private var colorCycle = 0.0
    @State private var steps = 100.0
    @State private var saturation = 1.0
    @State private var brightness1 = 1.0
    @State private var brightness2 = 0.5

    var body: some View {
        VStack {
            ColorCyclingCircle(amount: colorCycle, steps: steps, saturation: saturation, brightness1: brightness1, brightness2: brightness2)
                .frame(width: 300, height: 300)
                .onTapGesture {
                    withAnimation() {
                        saturation = saturation == 1 ? 0 : 1
                        colorCycle = colorCycle == 1 ? 0 : 1
                        saturation = saturation == 1 ? 0 : 1
                    }
                }

            Spacer()
                .frame(height: 100)
            
            Text("Color")
            Slider(value: $colorCycle)
            Text("Saturation")
            Slider(value: $saturation)
            Text("Brightness")
            Slider(value: $brightness1)
            Slider(value: $brightness2)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

CodePudding user response:

In struct ColorCyclingCircle, you're getting the wrong value for amount:

Change:

amount = newValue.first.first

to:

amount = newValue.first.second

Also, in this code:

.onTapGesture {
    withAnimation() {
        saturation = saturation == 1 ? 0 : 1
        colorCycle = colorCycle == 1 ? 0 : 1
        saturation = saturation == 1 ? 0 : 1
    }
}

you are changing saturation twice. The animation won't happen until after these values have been set, so the end result is that saturation goes to 0 if it started as anything but 1. That's surely not what you intended.

  • Related