ios – Different Animation behavior between Image from assets and from bundle


I want a balloon fly from bottom to top forever. Every fly the X start and duratoin is different.
In the first version, Balloon images were in a folder under the project. I made sure the load is good (‘Image(uiImage: uiImage)’), as i have checked the image render well. however, using withAnimation only cause fade in/out, but not move. Then i added a boarder to the image, and interesting, the image itself still fade in/out, but the boarder were flying….
In the seconde version, Balloon image are load from assets, and everything works well.
Here’s the code

struct BalloonView: View {
    @State private var balloonX: CGFloat = UIScreen.main.bounds.width / 2
    @State private var balloonY: CGFloat = 0

    private let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
    
    var body: some View {
        Image("ballon-blue-muti") // works well
//        BalloonView.loadAirBalloons()[0]  // Image are fade in/out, but board works
            .resizable()
            .scaledToFit()
            .frame(width: 50)
            .border(.black)
            .position(x: balloonX, y: balloonY)
            .onAppear {
                startBalloonAnimation(screenHeight: UIScreen.main.bounds.height)
            }
            .onReceive(timer) { _ in
                print("balloonX: \(balloonX), balloonY: \(balloonY)")
            }
    }

    private func startBalloonAnimation(screenHeight: CGFloat) {
        let screenWidth = UIScreen.main.bounds.width

        balloonX = CGFloat.random(in: 0...screenWidth)
        balloonY = screenHeight

        let duration = Double.random(in: 5...10)
        let endX = CGFloat.random(in: 0...screenWidth)

        withAnimation(Animation.linear(duration: duration)) {
            balloonY = screenHeight / 2
            balloonX = endX
        }

        DispatchQueue.main.asyncAfter(deadline: .now() + duration) {
            balloonY = screenHeight
            startBalloonAnimation(screenHeight: screenHeight)
        }
    }

    static private func loadAirBalloons() -> [Image] {
        if let path = Bundle.main.resourcePath {
            let imageFolder = path.appending("/images/balloons")
            do {
                let fileNames = try FileManager.default.contentsOfDirectory(atPath: imageFolder)
                return fileNames.compactMap { fileName in
                    if let uiImage = UIImage(contentsOfFile: "\(imageFolder)/\(fileName)") {
                        return Image(uiImage: uiImage)
                    }
                    return nil
                }
            } catch {
                print(error)
            }
        }
        return []
    }
}


struct Background: View {
    var body: some View {
        ZStack {
            BalloonView()
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.pink)
    }
}

i use folder because I don’t want to add new code when i add new images…Seems only bundle works for this.
So if still using Image(uiImage: uiImage) approach, how to fix it?
And why there’s different?

As I wrote, I load image from assets instead of Image(uiImage: uiImage)

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img