Быстрое создание цепочки анимации с использованием CGAffineTransforms - PullRequest
0 голосов
/ 08 января 2019

Я пытаюсь создать фоновую анимацию для своего приложения. То, что я пытаюсь добиться для части этого:

1) Изображение (случайный цвет / форма, выбранный из массива) появляется случайным образом на виде. 2) Затем он быстро увеличивается в размерах (от невидимого к видимому). 3) Затем будет медленно двигаться в заданном направлении, вращаясь, в течение 10 секунд. 4) Затем он уменьшится до невидимого размера и будет удален из вида.

Что я обнаружил, так это то, что фигура будет правильно отображаться на шагах 1 и 2. Затем форма перейдет в случайную позицию на экране в начале анимации / шага 3 (переход 3 в приведенном ниже коде). Пока он движется, он также уменьшается в размере. Затем на шаге 4 он возвращается к исходному положению на шагах 1 и 2, а затем сходит с экрана, как и предполагалось.

Я не могу на всю жизнь понять, что здесь происходит. Я надеюсь, что я не пропустил что-то смущающе очевидное.

Заранее спасибо за любую помощь!

class BackgroundAnimation {

func animation(animationView: UIView) {

    let colourArray = [
    UIColor(red:0.99, green:0.80, blue:0.05, alpha:1.0),
    UIColor(red:0.06, green:0.22, blue:0.29, alpha:1.0),
    UIColor(red:0.95, green:0.18, blue:0.30, alpha:1.0),
    UIColor(red:0.35, green:0.77, blue:0.92, alpha:1.0),
    UIColor(red:0.95, green:0.61, blue:0.19, alpha:1.0)
    ]

    let imageArray = [
    "Cross",
    "Circle",
    "Halfmoon",
    "Square",
    "Triangle"
    ]

    //Animation constants
    let initialDimensions = 10
    let pathLength: CGFloat = 100
    let pathDuration = 10
    let scaleFactor: CGFloat = 5
    let scaleDuration = 1

    //Select the random image and random colour that is to be animated.
    let image = UIImage(named: imageArray[Int.random(in: 0...imageArray.count - 1)])
    let imageView = UIImageView(image: image)


    imageView.image = imageView.image?.withRenderingMode(.alwaysTemplate)
    imageView.tintColor = colourArray[Int.random(in: 0...colourArray.count - 1)]
    imageView.contentMode = .scaleAspectFit
    imageView.frame = CGRect(x: 0, y: 0, width: initialDimensions, height: initialDimensions)
    animationView.insertSubview(imageView, at: 0)

    //create a random start location and angle of direction
    let startPointX = CGFloat.random(in: 0...animationView.frame.width)
    let startPointY = CGFloat.random(in: 0...animationView.frame.height)
    let pathAngle = CGFloat.random(in: 0...(CGFloat.pi * 2))
    imageView.center = CGPoint(x: startPointX, y: startPointY)

    //Calculate the endpoint from path angle and length
    let translationX = pathLength * sin(pathAngle)
    let tanslationY = -(pathLength * cos(pathAngle))


    //Define the transitions for the aniamtion
    var transition1 = CGAffineTransform.identity
    transition1 = transition1.scaledBy(x: scaleFactor, y: scaleFactor)


    var transition2 = CGAffineTransform.identity
    transition2 = transition2.translatedBy(x: translationX, y: tanslationY)
    transition2 = transition2.rotated(by: CGFloat.random(in: CGFloat.pi * 1/4 ... CGFloat.pi * 3/4))


    var transition3 = CGAffineTransform.identity
    transition3 = transition3.scaledBy(x: 0.001, y: 0.001)




    UIView.animate(withDuration: TimeInterval(scaleDuration), delay: 0, options: .beginFromCurrentState, animations: {

        imageView.transform = transition1

    }, completion: {finished in

        UIView.animate(withDuration: TimeInterval(pathDuration), delay: 0, options: .beginFromCurrentState, animations: {

            imageView.transform = transition2

        }, completion: { finished in

            UIView.animate(withDuration: TimeInterval(scaleDuration), delay: 0, options: .beginFromCurrentState, animations: {

                imageView.transform = transition3

            }, completion: { finished in

                imageView.removeFromSuperview()

            })

        })

    })

}

}

Ответы [ 2 ]

0 голосов
/ 10 января 2019

В отношении полезного ответа Эсана:

Это исправило проблему с перемещением, но imageView становится меньше, когда я пытаюсь применить вращение во втором анимационном блоке. Обновленный код ниже:

class BackgroundAnimation {

func animation(animationView: UIView) {

    let colourArray = [
    UIColor(red:0.99, green:0.80, blue:0.05, alpha:1.0),
    UIColor(red:0.06, green:0.22, blue:0.29, alpha:1.0),
    UIColor(red:0.95, green:0.18, blue:0.30, alpha:1.0),
    UIColor(red:0.35, green:0.77, blue:0.92, alpha:1.0),
    UIColor(red:0.95, green:0.61, blue:0.19, alpha:1.0)
    ]

    let imageArray = [
    "Cross",
    "Circle",
    "Halfmoon",
    "Square",
    "Triangle"
    ]

    //Animation constants
    let initialDimensions = 10
    let pathLength: CGFloat = 100
    let pathDuration = 10
    let scaleFactor: CGFloat = 3
    let scaleDuration = 1

    //Select the random image and random colour that is to be animated.
    let image = UIImage(named: imageArray[Int.random(in: 0...imageArray.count - 1)])
    let imageView = UIImageView(image: image)


    imageView.image = imageView.image?.withRenderingMode(.alwaysTemplate)
    imageView.tintColor = colourArray[Int.random(in: 0...colourArray.count - 1)]
    imageView.contentMode = .scaleAspectFit
    imageView.frame = CGRect(x: 0, y: 0, width: initialDimensions, height: initialDimensions)
    animationView.insertSubview(imageView, at: 0)

    //create a random start location and angle of direction
    let startPointX = CGFloat.random(in: 0...animationView.frame.width * 0.9)
    let startPointY = CGFloat.random(in: 0...animationView.frame.height * 0.9)
    let pathAngle = CGFloat.random(in: 0...(CGFloat.pi * 2))
    imageView.center = CGPoint(x: startPointX, y: startPointY)

    //Calculate the endpoint from path angle and length
    let translationX = pathLength * sin(pathAngle)
    let translationY = (pathLength * cos(pathAngle))

    let endPointX = startPointX + translationX
    let endPointY = startPointY + translationY

    //Define the transitions for the aniamtion
    var transition1 = CGAffineTransform.identity
    transition1 = transition1.scaledBy(x: scaleFactor, y: scaleFactor)


    var transition2 = CGAffineTransform.identity
    transition2 = transition2.rotated(by: CGFloat.random(in: CGFloat.pi * 1/4 ... CGFloat.pi * 3/4))



    var transition3 = CGAffineTransform.identity
    transition3 = transition3.scaledBy(x: 0.001, y: 0.001)




    UIView.animate(withDuration: TimeInterval(scaleDuration), delay: 0, options: .beginFromCurrentState, animations: {

        imageView.transform = transition1

    }, completion: {finished in

        UIView.animate(withDuration: TimeInterval(pathDuration), delay: 0.5, options: [.beginFromCurrentState, .curveLinear], animations: {

            imageView.frame.origin = CGPoint(x: endPointX, y: endPointY)
            imageView.transform = transition2

        }, completion: { finished in

            UIView.animate(withDuration: TimeInterval(scaleDuration), delay: 0.5, options: .beginFromCurrentState, animations: {

                imageView.transform = transition3

            }, completion: { finished in

                imageView.removeFromSuperview()

            })

        })

    })

}

}

0 голосов
/ 09 января 2019

измените свою позицию с помощью imageView.center ИЛИ imageView.frame.origin

imageView.frame.origin = CGPoint(x: translationX, y: tanslationY)

но вы должны вычислить пункт назначения, а затем установить frame.origin в пункт назначения

...