Search code examples
swiftanimationbuttonswiftuishazam

Animation of Shazam's button in SwiftUI


I would like to make an animation like Shazam's Button but I can't manage to do it...

Anyone have an idea how to make this animation in SwiftUI?

Here is the code :

import SwiftUI
import Foundation

struct SpeechButton: View {
    
    @State var isPressed:Bool = false

    var body: some View {
        
        Button(action:{
            
        }){
            ZStack {
                
    //-->       // if self.isPressed { RoundAnimation() }
                
                Image(systemName: "waveform")// Button Image
                    .resizable()
                    .frame(width: 40, height: 40)
                    .foregroundColor(.white)
                    
            }
        )
    }
}

Thanks in advance for your help people :)


Solution

  • After your code update even has more issue with it, it was not runnable, how ever you just gave me an Empty Button to work on it!

    Here I got some thing for you:

        import SwiftUI
    
    
    struct ContentView: View {
        
        @State var startAnimation: Bool = false
        @State var random: CGFloat = 0
        
        var timer = Timer.publish (every: 0.1, on: .main, in: .common).autoconnect()
        
        var body: some View {
            
    
    
            Button(action: {
                
                // your logic!
                
            }){
    
                ZStack
                {
                    Circle()
                        .fill(Color(UIColor.systemTeal))
     
                    
                    Image(systemName: "waveform")
                        .resizable()
                        .frame(width: 100, height: 100)
                    
                    
                }
                .frame(width: 200, height: 200)
                .scaleEffect(startAnimation ? CGFloat(1*random) : 1 )
                .animation(.easeInOut)
                .onTapGesture {
                    startAnimation.toggle()
    
                    if startAnimation == false
                    {
                        timer.upstream.connect().cancel()
    
                    }
      
                }
        
                
            }
            .onReceive(timer) { _ in
                
                random = CGFloat.random(in: 0.5...1)
                
            }
    
            
            
            
        }
        
    }
    

    Update Code: Version 2.0.0

    import SwiftUI
    
    
    struct ContentView: View {
        
        @State var startAnimation: Bool = false
        @State var random: CGFloat = 0
        
    
        @State var timer = Timer.publish(every: 0.1, on: .main, in: .common).autoconnect()
        
        
        func stopTimer() {
            timer.upstream.connect().cancel()
        }
        
        func startTimer() {
            timer = Timer.publish(every: 0.1, on: .main, in: .common).autoconnect()
        }
        
        
        
        var body: some View {
            
    
    
            Button(action: {
                
                // your logic!
                
            }){
    
                ZStack
                {
                    Circle()
                        .fill(RadialGradient(gradient: Gradient(colors: [Color(UIColor.systemTeal), Color.white.opacity(0.1)]), center: .center, startRadius: 0, endRadius: 180))
     
                    
                    Image(systemName: "waveform")
                        .resizable()
                        .frame(width: 100, height: 100)
                    
                    
                }
                .frame(width: 200, height: 200)
                .scaleEffect(startAnimation ? random : 1 )
                .animation(.easeInOut)
                .onTapGesture {
                    startAnimation.toggle()
    
                    if startAnimation == false
                    {
                        stopTimer()
    
                    }
                    else
                    {
                        startTimer()
                    }
      
                }
        
                
            }
            .onReceive(timer) { _ in
                random = CGFloat.random(in: 0.5...1)
            }
            .onAppear()
            {
                stopTimer()
            }
    
            
            
            
        }
        
    }
    

    Update Code: Version 3.0.0 Much more and better Animation

        import SwiftUI
    
    
    struct ContentView: View {
        
        @State var startAnimation: Bool = false
        @State var random1: CGFloat = 0.5
        @State var random2: CGFloat = 0.5
        
        
        @State var timer = Timer.publish(every: 0.3, on: .main, in: .common).autoconnect()
        
        
        func stopTimer() {
            timer.upstream.connect().cancel()
        }
        
        func startTimer() {
            timer = Timer.publish(every: 0.3, on: .main, in: .common).autoconnect()
        }
        
        
        
        var body: some View {
            
            
            
            Button(action: {
                
                // your logic!
                
            }){
                
                ZStack
                {
                    
                    
                    Circle()
                        .fill(RadialGradient(gradient: Gradient(colors: [Color(UIColor.systemTeal), Color.white.opacity(0.1)]), center: .center, startRadius: 0, endRadius: 400))
                        .frame(width: random2*500, height: random2*500)
                    
                    Circle()
                        .fill(RadialGradient(gradient: Gradient(colors: [Color(UIColor.gray), Color.white.opacity(0.01)]), center: .center, startRadius: 0, endRadius: 400))
                        .frame(width: random1*400, height: random1*400)
                    
                    
                    Circle()
                        .fill(RadialGradient(gradient: Gradient(colors: [Color(UIColor.systemTeal), Color.white.opacity(0.1)]), center: .center, startRadius: 150, endRadius: 190))
                        .frame(width: 200, height: 200)
                    
                    Image(systemName: "waveform")
                        .resizable()
                        .frame(width: 100, height: 100)
                    
                    
                }
                
                .scaleEffect(startAnimation ? random1 : 1 )
                .animation(.easeInOut)
                .onTapGesture {
                    startAnimation.toggle()
                    
                    if startAnimation == false
                    {
                        stopTimer()
                        
                    }
                    else
                    {
                        startTimer()
                    }
                    
                }
                
                
            }
            .onReceive(timer) { _ in
                random1 = CGFloat.random(in: 0.5...1)
                random2 = CGFloat.random(in: 0.5...1)
                print(random1, random2)
            }
            .onAppear()
            {
                stopTimer()
            }
            
            
            
            
        }
        
    }
    

    enter image description here