Как добавить анимацию на CGAffineTransform для RotateAngle в SwiftUI? - PullRequest
0 голосов
/ 19 сентября 2019

Мне нужно анимировать CGAffineTransform с помощью RotateAngle, но я не знаю, возможно ли это, потому что CGAffineTransform не соответствует Animatable.Мэйби с «withAnimation», но я не понимаю, как это использовать.Я знаю, что могу использовать вращение-эффект, но для некоторых целей мне нужно использовать CGAffineTransform.

Мой код:

import SwiftUI
import CoreLocation

struct Arrow: View {

  var locationManager = CLLocationManager()
  @ObservedObject var location: LocationManager = LocationManager()

  private var animationArrow: Animation {
    Animation
      .easeInOut(duration: 0.2)
  }

  var body: some View {
    VStack {
      Image("arrow")
        .resizable()
        .aspectRatio(contentMode: .fit)
        .frame(width: 300, height: 300)
        .transformEffect(
          CGAffineTransform(translationX: -150, y: -150)
            .concatenating(CGAffineTransform(rotationAngle: CGFloat(-location.heading.degreesToRadians)))
            .concatenating(CGAffineTransform(translationX: 150, y: 150))
        )
        .animation(animationArrow)

      Text(String(location.heading.degreesToRadians))
        .font(.system(size: 20))
        .fontWeight(.light)
        .padding(.top, 15)

      Text(String(location.coordinates[0]))
        .font(.system(size: 20))
        .fontWeight(.light)
        .padding(.top, 15)

      Text(String(location.coordinates[1]))
        .font(.system(size: 20))
        .fontWeight(.light)
        .padding(.top, 15)
    }
  }
}

1 Ответ

1 голос
/ 19 сентября 2019

Если вы не можете использовать какой-либо из существующих анимируемых эффектов, вам нужно научить SwiftUI анимировать матрицу преобразования.Вы делаете это с GeometryEffect.Это протокол, который соответствует как Animatable, так и ViewModifier.

Если вы хотите получить полное объяснение того, как работает GeometryEffect, проверьте мой пост: https://swiftui -lab.com / swiftui-animations-part2 /

Вот рабочий пример:

struct ContentView: View {
    @State private var animate = false

    var body: some View {
        Rectangle()
            .frame(width: 50, height: 50)
            .modifier(MyEffect(angle: animate ? .pi * 2 : 0))
            .onTapGesture {
                withAnimation(.easeInOut(duration: 2.0)) {
                    self.animate.toggle()
                }
        }
    }
}

struct MyEffect: GeometryEffect {
    var angle: CGFloat

    var animatableData: CGFloat {
        get { angle }
        set { angle = newValue }
    }

    func effectValue(size: CGSize) -> ProjectionTransform {
        return ProjectionTransform(CGAffineTransform(rotationAngle: angle))
    }
}

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

struct ContentView: View {
    @State private var angle: CGFloat = 0

    var body: some View {
        VStack {
            Rectangle()
                .frame(width: 50, height: 50)
                .modifier(MyEffect(angle: angle))

            Button("Go to 0") {
                withAnimation(.easeInOut(duration: 2.0)) {
                    self.angle = 0
                }
            }

            Button("Go to 360") {
                withAnimation(.easeInOut(duration: 2.0)) {
                    self.angle = .pi * 2
                }
            }
        }
    }
}
...