В SwiftUI я работаю с двумя экранами: экраном A и экраном B. Я пытаюсь создать эффект перехода, используя функцию согласованной геометрии SwiftUI. При переходе используются два скругленных прямоугольника: один на Экране А, который выглядит как круг из-за радиуса угла и размера, а другой на Экране Б с нулевым радиусом угла, служащий фоном.
Ожидаемое поведение:
Я ожидал, что анимация будет отображаться как плавный переход одного объекта из одной конфигурации в другую, в частности, с изменением углового радиуса, высоты и ширины.
Фактическое поведение:
Однако, хотя на первый взгляд именно это и происходит, если вы присмотритесь, вы увидите, что переход больше похож на плавное затухание. По мере исчезновения исходная форма интерполирует свой угловой радиус в сторону целевой конфигурации, но целевая форма по мере ее исчезновения не интерполирует из исходного радиуса.< /п> Этот снимок экрана с верхней правой частью анимации, прошедшей примерно на 50 %, иллюстрирует нежелательное поведение:

Кажется маловероятным, что перекрестное затухание можно просто «отключить»… Я полагаю, что перекрестное затухание может быть важным для эффекта matchedGeometry, поскольку кажется, что это единственный способ интерполяции между определенными свойствами, например, различной заливкой. .. но даже если это правда, это не было бы очевидно, если бы только целевая фигура также интерполировала свою форму... чего в данном случае нет.
Мне бы хотелось, чтобы любой ответ не менял механизм анимации — это всего лишь упрощенная версия более крупного проекта. Анимация должна запускаться с помощью withAnimation{} и воздействовать на navController.screen.
Минимальный пример кода:
Главный экран:
энум Экран { основной регистр, цель } @Наблюдаемый класс Нав { вар экран: Screen = .main } структура ContentView: Просмотр { @Environment(Nav.self) var navController // согласованная геометрия @Namespace переменное пространство имен var body: some View { переключить navController.screen { случай .основной: ZStack{ RoundedRectangle (cornerRadius: 15) .fill(Цвет.зеленый) .matchedGeometryEffect(id: "circleToBackground", в: пространстве имен) .frame(ширина: 30, высота: 30) .onTapGesture { withAnimation(.easeInOut(длительность: 4.0)){ navController.screen = .target } } } случай .цель: TargetScreen (пространство имен: пространство имен) } } } Целевой экран:
struct TargetScreen: View { пусть пространство имен: Namespace.ID @Environment(Nav.self) var navController var body: some View { ZStack { RoundedRectangle (cornerRadius: 0) .fill(LinearGradient(colors: [Color.green, Color.white], startPoint: UnitPoint(x:0.5,y:0.0), endPoint: UnitPoint(x:0.5,y:1.0))) .matchedGeometryEffect(id: "circleToBackground", в: пространстве имен) .frame(maxWidth: .infinity, maxHeight: .infinity) Text("BACK").onTapGesture { сАнимацией { navController.screen = .main } } } } }