1

I am trying to create an animation where a small heart icon is pumping. I have the two images I believe are sufficient to create the effect, but I have no idea how to create this animation effect. I have tried several things and none of them seem to work.

Any help you can offer will be greatly appreciated.

Here's what I have so far:

@State var show : Bool = false
    var body: some View {
        VStack(alignment: .trailing){
            ZStack{
                BlackView()
                if(show){
                    Image("heartOrgan1")
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .frame(width: 50, height:50)
                        .hidden()
                        
                    Image("heartOrgan")
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .frame(width: 50, height: 50)
                    
                } else {
                    Image("heartOrgan1")
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .frame(width: 50, height: 50)
                        
                    Image("heartOrgan")
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .frame(width: 50, height: 50)
                        .hidden()
                }
            }
            .onAppear(){
                
                withAnimation { self.show.toggle()}
            }
        }
    }

The general idea is to loop the switching between two heart images that represent a heart beating. I am interested in using these particular heart images as they look like actual hearts, and I like that.

Justin A
  • 377
  • 5
  • 17
  • Next should be helpful https://stackoverflow.com/a/63536007/12299030. – Asperi Jan 08 '21 at 05:29
  • 1
    Does this answer your question? [Delay a repeating animation in SwiftUI with between full autoreverse repeat cycles](https://stackoverflow.com/questions/65509795/delay-a-repeating-animation-in-swiftui-with-between-full-autoreverse-repeat-cycl) – pawello2222 Jan 08 '21 at 15:09
  • It comes close. But my images are not just scaled-up versions of each other. The heart images are a little more detailed and closely resemble actual hearts. – Justin A Jan 08 '21 at 15:12
  • 1
    Now with two possible solutions you have something to *try* at least. Please show your code and we'll try to help you fix it. – pawello2222 Jan 08 '21 at 15:47
  • @pawello2222 please take a look. I just updated my question. Also, I have added my attempt which does nothing. My goal is to loop the animating of these two particular images to simulate the heart pumping in a loop. – Justin A Jan 09 '21 at 02:09
  • Please make your attempt reproducible - what are *settings* in `.frame(width: settings.unitHeartViewImageSize, height: settings.unitHeartViewImageSize)`? – pawello2222 Jan 09 '21 at 18:06
  • @pawello2222 I have simplified it considerably. Removed all the variables. Thanks again for your patience and for taking the time to look at this. – Justin A Jan 09 '21 at 23:00
  • @JustinA I'm not sure I understand what you want to achieve but here are two tips: 1) if you want to follow with your example you can specify animations directly in the `withAnimation` block like: `withAnimation(Animation.linear(duration: 1).repeatForever(autoreverses: false)) { ... }` 2) I still believe you can use the animation from https://stackoverflow.com/a/65511599/8697793 - just display a different image basing on the `heartState` property. – pawello2222 Jan 12 '21 at 00:24

1 Answers1

2

You don't necessarily need two images for this. You can use one image and apply the scale effect on it. Make the one image scale up and add a delay to it. Then make it repeat.

Example:

@State private var animationAmount: CGFloat = 1

var body: some View {
    ZStack {
        Color.black

        Image(systemName: "heart.fill")
            .resizable()
            .frame(width: 50, height: 50)
            .foregroundColor(.red)
            .scaleEffect(animationAmount)
            .animation(
                .linear(duration: 0.1)
                    .delay(0.2)
                    .repeatForever(autoreverses: true),
                value: animationAmount)
            .onAppear {
                animationAmount = 1.2
            }
    }
}

You can also change the decimal value in inside the delay() to have different heartbeats. The heartbeat looks consistent with delays between 0.1 - 0.4.

James Castrejon
  • 321
  • 2
  • 15