前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SwiftUI案例:自定义加载动画

SwiftUI案例:自定义加载动画

作者头像
DioxideCN
发布2022-08-05 19:21:57
1.9K0
发布2022-08-05 19:21:57
举报
文章被收录于专栏:用户4480853的专栏

SwiftUI案例:自定义加载动画

效果

效果
效果

目标

  • 使用图片实现自定义加载动画
  • 点击加载弹出层外部任意一点可关闭动画演示
  • 开关可控制图片采用“垂直移动动画”或“垂直加自身旋转动画”

外观配置

配置
配置

视图的实现

ContentView.swift

案例通过在间隔时间内不断控制变量 animateBall:BoolanimateRotation:Bool 的值来间接地实现动画效果;

代码语言:javascript
复制
import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationView {
            Home()
            //使用Home()组件定义导航栏标题
                .navigationTitle("弹跳的球动画")
        }
    }
}

//全局暴露ContentView()组件
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        //实例化当前页面容器
        ContentView()
    }
}


struct Home: View {
    //rotateBall与showPopUp组成的flag标签组
    @State var rotateBall = false //是否旋转图片
    @State var showPopUp = false //是否显示弹出层
    
    @Environment(\.colorScheme) var scheme //使用预处理颜色组
    
    var body: some View {
        //创建纵向布局视图
        VStack {
            //"图片是否旋转"开关
            Toggle(isOn: $rotateBall) {
                Text("图片是否旋转")
            }
            .padding()
            .padding(.horizontal, 10)
            //弹出演示按钮
            Button {
                withAnimation(.spring()) {
                    showPopUp.toggle()
                }
            }
            //设置按钮的label内容
            label: {
                Text("弹出演示")
                    .foregroundColor(.black)
                    .padding(.vertical, 10)
                    .padding(.horizontal, 25)
                    .background(scheme == .dark ? Color.black : Color.white)
                    .cornerRadius(8)
                    .shadow(color: Color.primary.opacity(0.1), radius: 5, x: 5, y: 5)
                    .shadow(color: Color.primary.opacity(0.1), radius: 5, x: -5, y: -5)
            }
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .overlay(
            //覆盖层
            ZStack {
                //如果"showPopUp"的flag是真则显示这个覆盖层
                if showPopUp {
                    Color.primary.opacity(0.2)
                        .ignoresSafeArea()
                        .onTapGesture {
                            withAnimation(.spring()) {
                                showPopUp.toggle()
                            }
                        }
                    //调用"DribbleAnimatedView"视图组件
                    DribbleAnimatedView(showPopUp: $showPopUp, rotateBall: $rotateBall)
                }
            }
        )
    }
}

//视图DribbleAnimatedView加载组件
struct DribbleAnimatedView: View {
    //颜色配置
    @Environment(\.colorScheme) var scheme
    //需要函数调用时显式地传入这些flag组值
    @Binding var showPopUp: Bool //使用全局showPopUp变量
    @Binding var rotateBall: Bool //使用全局rotateBall变量
    //动画绑定变量
    @State var animateBall = false //是否显示动画
    @State var animateRotation = false //是否旋转
    
    var body: some View {
        ZStack {
            //调用全局scheme颜色配置并使用ZStack布局
            (scheme == .dark ? Color.black : Color.white)
                .frame(width: 150, height: 150)
                .cornerRadius(14)
                .shadow(color: Color.primary.opacity(0.1), radius: 5, x: 5, y: 5)
                .shadow(color: Color.primary.opacity(0.1), radius: 5, x: -5, y: -5)
            
            //动画球的底部阴影设置
            Circle()
                .fill(Color.gray.opacity(0.4))
                //大小和尺寸使用animateBall:Bool动画的返回值来控制
                .frame(width: animateBall ?  40 : 20, height: 40)
                .rotation3DEffect(
                    .init(degrees: 70),
                    axis: (x: 1, y: 0, z: 0),
                    anchor: .center
                )
                .offset(y: 35)
                //透明度使用animateBall:Bool动画的返回值来控制
                .opacity(animateBall ? 1 : 0)
            
            //使用图片"dirbble.jpeg"
            Image("dirbble")
                .resizable()
                .clipShape(Circle())
                .aspectRatio(contentMode: .fit)
                .frame(width: 60, height: 60)
                //旋转角度使用animateBall:Bool动画的返回值来控制
                .rotationEffect(.init(degrees: rotateBall && animateRotation ? 360 : 0))
                //位移偏量使用animateBall:Bool动画的返回值来控制
                .offset(y: animateBall ? 10 : -25)
        }
        //显示的时候自动调用doAnimation()函数显示动画
        .onAppear {
            doAnimation()
        }
    }
    //doAnimation()动画控制组件
    func doAnimation(){
        withAnimation(Animation.easeInOut(duration:0.6).repeatForever(autoreverses: true)) {
            //0.6秒内不断切换animateBall的Bool值
            //控制纵向弹跳的动画
            animateBall.toggle()
        }
        withAnimation(Animation.easeInOut(duration:0.8).repeatForever(autoreverses: true)) {
            //0.8秒内不断切换animateRotation的Bool值
            //控制旋转
            animateRotation.toggle()
        }
        
    }
}

CenterLoadingAnimationUI.zip

来源:百度网盘 | 提取码:gw4l

CenterLoadingAnimationUI.zip

来源:蓝奏云网盘 | 提取码:5uih

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • SwiftUI案例:自定义加载动画
    • 效果
      • 目标
        • 外观配置
          • 视图的实现
            • ContentView.swift
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档