动画视图和过渡

运用SwiftUI时,不管作用在哪里,您都能够单独为视图或视图状况的更改增加动画作用。SwiftUI为您处理这些组合、重叠和可中断动画的一切杂乱性。

在本教程中,您将为包含图表的视图制造动画,该视图用于盯梢用户在运用Landmarks应用程序时徒步旅行。运用animation(_:)润饰符,您将看到为视图制造动画是多么简单。

下载初学者项目并遵从本教程,或翻开已完结的项目并自行探究代码。

第一节 将徒步旅行数据增加到应用程序中

在增加动画之前,您需求一些动画。在本节中,您将导入和建模徒步旅行数据,然后增加一些预构建的视图,以便在图表中静态显现该数据。

第一步 增加资源文件

下载初学者项目,在Resources文件下找到hikeData.json,拖入您的工程Resources目录下

第二步 创立模型Hike.swift

运用菜单项文件>新建>文件,在项目的模型组中创立一个名为Hike.swift的新Swift文件。
Landmark结构相同,Hike结构契合Codable,并具有与相应数据文件中的键匹配的特点。

import Foundation
struct Hike: Codable, Hashable, Identifiable {
    var id: Int
    var name: String
    var distance: Double
    var difficulty: Int
    var observations: [Observation]
    static var formatter = LengthFormatter()
    var distanceText: String {
        Hike.formatter
            .string(fromValue: distance, unit: .kilometer)
    }
    struct Observation: Codable, Hashable {
        var distanceFromStart: Double
        var elevation: Range<Double>
        var pace: Range<Double>
        var heartRate: Range<Double>
    }
}

第三步 将hikes数组加载到您的模型对象中。

由于您在开始加载后永远不会修正徒步旅行数据,因此您无需运用@Published特点对其进行标记。

final class ModelData: ObservableObject {
   @Published var landmarks:[Landmark] = load("landmarkData.json")
    var hikes: [Hike] = load("hikeData.json")
}

第四步 增加Hikes资源文件

Hikes文件夹从下载文件的资源文件夹拖到项目的视图组中。在单击完结之前,请必须选择“假如需求仿制项目”和“创立组”。

第五步 预览

HikeView.swift中,翻开实时预览,并测验显现和隐藏图表。

请必须在整个教程中运用实时预览,以便您能够测验每个过程的结果。

第二节 给视图增加动画

在等价视图上运用animation(:)修正器时,且视图的可动画特点发生改变时,swiftUI会生成一个动画。
视图的色彩、不透明度、旋转、大小和其他特点都能够设置动画。当视图不等价,能够运用animation(
:value:)修正器在指定值更改时启动动画。

第一步 按钮旋转时增加动画

HikeView.swift中,经过增加一个动画润饰器,当showDetail的值发生改变时,按钮开始旋转,

.animation(.easeInOut, value: showDetail)

第二步 按钮增加扩大动画

当图形可见时,给按钮增加一个扩大动画

.scaleEffect(showDetail ? 1.5 : 1.0)

第三步 更改动画类型

把动画类型easeInOut改成spring().

.animation(.spring(), value: showDetail)

swiftUI包含预界说或自界说的根底动画,以及弹簧和流体动画。能够调整动画的速度,在动画开始前设置推迟,或许指定动画重复

第四步 封闭旋转动画

scaleEffect润饰器上方再增加一个动画润饰器,动画类型设置成nil

.animation(nil, value: showDetail)

第五步 移除动画润饰器

在进行下一步之前,先移除之前增加的两个动画润饰器

第三节 状况改变时生成动画

现在您现已学会了怎么给某个视图增加动画,是时候依据状况改变增加动画了。
在这里,您将对用户点击按钮并切换showDetail状况特点时发生的一切更改应用动画。

第一步 运用withAnimation

用withAnimation函数包装showDetail.toggle()的调用。
受showDetail特点影响的两个视图(按钮和HikeDetail视图)现在都有动画过渡。

第二步 设置动画时长

传递一个4秒时间的根底动画,您能够传递和animation(_:value:)相同的动画

第三步 在动画的过程中,测验翻开和封闭图形视图

在进行下一步之前,先清除withAnimation的参数

第四节 自界说转场动画

默许情况下,视图的转场作用是渐隐渐现的,您能够经过transition(_:)润饰器来自界说转场动画

第一步 给HikeView.swift 增加一个transition(_:)润饰器

if showDetail { HikeDetail(hike: hike) .transition(.slide)

现在图形展现和消失都会有滑动作用了

第二步 提取转场代码

提取刚刚增加为AnyTransition静态特点的转场,并在视图的转场修正器中拜访新特点。
当您扩展自界说转场时,这将使您的代码尽可能的干净

extension AnyTransition {
    static var moveAndFade: AnyTransition {
        AnyTransition.slide
    }
}

第三步 切换slide->move(edge:)

运用slide图形从左边滑入屏幕,右侧滑出屏幕, 将slide换成move(edge:),使视图滑入滑出都在左边

extension AnyTransition {
    static var moveAndFade: AnyTransition {
        AnyTransition.move(edge: .trailing)
    }
}

第四步 运用非对称润饰器 asymmetric(insertion:removal:)

当视图显现和消失时,运用asymmetric(insertion:removal:)能够供给不同的转场动画。比如:
显现时,需求从右侧进入,且伴随着透明度逐步显现。
消失时,需求缩小,且伴随着透明度逐步消失。

extension AnyTransition {
    static var moveAndFade: AnyTransition {
        .asymmetric(
            insertion: .move(edge: .trailing).combined(with: .opacity),
            removal: .scale.combined(with: .opacity))
    }
}

第五节 为杂乱的作用组合动画

单击条形图下方的按钮时,图形会在三组不同的数据之间切换。在本节中,您将运用组成动画为构成图形的胶囊供给一个动态的波纹过渡。

第一步 修正showDetail为true

在HikeView中,将showDetail的默许值更改为true,然后将预览固定到画布上。
这样,当您在另一个文件中处理动画时,就能够在上下文中看到图形。

第二步 在HikeGraph.swift中,界说一个新的波纹动画,并将其应用于每个生成的图形胶囊。

extension Animation { static func ripple() -> Animation { Animation.default }}

第三步 将动画切换到弹簧动画,削减阻尼分数以使钢筋跳跃。

经过在实时预览中切换仰角、心率和速度,能够看到动画的作用。

extension Animation {
    static func ripple() -> Animation {
        Animation.spring(dampingFraction: 0.5)
    }
}

第四步 将动画加快一点,以缩短每个条移动到其新方位所需的时间。

第五步 依据方位增加推迟

extension Animation {
    static func ripple(index: Int) -> Animation {
        Animation.spring(dampingFraction: 0.5)
            .speed(2)
            .delay(0.03 * Double(index))
    }
}

第六步 调查作用

调查自界说动画在图形之间转换时怎么供给波纹作用。
在继续下一个教程之前,请确保取消固定预览,即showDetail改为false