【问题标题】:Fill circle with wave animation in SwiftUI在 SwiftUI 中用波浪动画填充圆圈
【发布时间】:2020-08-13 14:11:07
【问题描述】:

我在 swiftUI 中创建了一个圆圈,我想用正弦波动画填充它以实现水波效果/动画。我想用类似的外观填充它:

下面是我的代码:

import SwiftUI

struct CircleWaveView: View {
    var body: some View {
        Circle()
            .stroke(Color.blue, lineWidth: 10)
            .frame(width: 300, height: 300)
    }
}

struct CircleWaveView_Previews: PreviewProvider {
    static var previews: some View {
        CircleWaveView()
    }
}

我想主要在 SwiftUI 上实现它,以便我可以支持暗模式!感谢您的帮助!

【问题讨论】:

    标签: swift swiftui


    【解决方案1】:

    这是一个完整的独立示例。它具有一个滑块,可让您更改百分比:

    import SwiftUI
    
    struct ContentView: View {
        
        @State private var percent = 50.0
        
        var body: some View {
            VStack {
                CircleWaveView(percent: Int(self.percent))
                Slider(value: self.$percent, in: 0...100)
            }
            .padding(.all)
        }
    }
    
    struct Wave: Shape {
    
        var offset: Angle
        var percent: Double
        
        var animatableData: Double {
            get { offset.degrees }
            set { offset = Angle(degrees: newValue) }
        }
        
        func path(in rect: CGRect) -> Path {
            var p = Path()
    
            // empirically determined values for wave to be seen
            // at 0 and 100 percent
            let lowfudge = 0.02
            let highfudge = 0.98
            
            let newpercent = lowfudge + (highfudge - lowfudge) * percent
            let waveHeight = 0.015 * rect.height
            let yoffset = CGFloat(1 - newpercent) * (rect.height - 4 * waveHeight) + 2 * waveHeight
            let startAngle = offset
            let endAngle = offset + Angle(degrees: 360)
            
            p.move(to: CGPoint(x: 0, y: yoffset + waveHeight * CGFloat(sin(offset.radians))))
            
            for angle in stride(from: startAngle.degrees, through: endAngle.degrees, by: 5) {
                let x = CGFloat((angle - startAngle.degrees) / 360) * rect.width
                p.addLine(to: CGPoint(x: x, y: yoffset + waveHeight * CGFloat(sin(Angle(degrees: angle).radians))))
            }
            
            p.addLine(to: CGPoint(x: rect.width, y: rect.height))
            p.addLine(to: CGPoint(x: 0, y: rect.height))
            p.closeSubpath()
            
            return p
        }
    }
    
    struct CircleWaveView: View {
        
        @State private var waveOffset = Angle(degrees: 0)
        let percent: Int
        
        var body: some View {
    
            GeometryReader { geo in
                ZStack {
                    Text("\(self.percent)%")
                        .foregroundColor(.black)
                        .font(Font.system(size: 0.25 * min(geo.size.width, geo.size.height) ))
                    Circle()
                        .stroke(Color.blue, lineWidth: 0.025 * min(geo.size.width, geo.size.height))
                        .overlay(
                            Wave(offset: Angle(degrees: self.waveOffset.degrees), percent: Double(percent)/100)
                                .fill(Color(red: 0, green: 0.5, blue: 0.75, opacity: 0.5))
                                .clipShape(Circle().scale(0.92))
                        )
                }
            }
            .aspectRatio(1, contentMode: .fit)
            .onAppear {
                withAnimation(Animation.linear(duration: 2).repeatForever(autoreverses: false)) {
                self.waveOffset = Angle(degrees: 360)
                }
            }
        }
    }
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            CircleWaveView(percent: 58)
        }
    }
    

    【讨论】:

    • 嗨@vacawama。我怎样才能在水滴(不是圆形)的图像中实现相同的效果?
    • @varoons,如果你的水滴是Shape,你应该可以在上面的代码中用WaterDrop()替换Circle()
    猜你喜欢
    • 2014-03-29
    • 2021-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多