【SwiftUI模块】0016、SwiftUI搭建一个水波纹动画效果

SwiftUI模块系列 - 已更新16篇
SwiftUI项目 - 已更新1个项目
往期Demo源码下载

技术:SwiftUI、SwiftUI3.0、水波纹、动画、水波纹动画
运行环境:
SwiftUI3.0 + Xcode13.4.1 + MacOS12.5 + iPhone Simulator iPhone 13 Pro Max

概述

使用SwiftUI搭建一个水波纹动画效果

详细

一、运行效果

请添加图片描述

二、项目结构图

在这里插入图片描述

三、程序实现 - 过程

思路:

  1. 先通过Canvas画出波浪形状
    在这里插入图片描述
  2. 填充底部颜色
    在这里插入图片描述
  1. 使用TimelineView 时间视图 进行一个类似帧动画的渲染 。渲染的返回就是当前水纹路径 从 负的屏幕 到当前屏幕 再到 超出的屏幕一个类似帧动画效果
  2. 添加多一个水纹面板 进行反向运动 看起来就像水波纹运动效果

1.创建一个项目命名为 Canvas

在这里插入图片描述
在这里插入图片描述

1.1.引入资源文件和颜色

无资源和颜色

2. 创建一个虚拟文件New Group 命名为 View

在这里插入图片描述
在这里插入图片描述

3. 创建一个文件New File 选择SwiftUI View类型 命名为Home

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

Code

ContentView - 主窗口

主要是展示主窗口Home

//
//  ContentView.swift
//  Shared
//
//  Created by lyh on 2022/8/27.
//

import SwiftUI

struct ContentView: View {
    
    
    var body: some View {
    
    
        Home()
    }
}

struct ContentView_Previews: PreviewProvider {
    
    
    static var previews: some View {
    
    
        ContentView()
    }
}

Home - 主页

思路

  1. 先通过Canvas画出波浪形状
    在这里插入图片描述
  2. 填充底部颜色
  3. 使用TimelineView 时间视图 进行一个类似帧动画的渲染 。渲染的返回就是当前水纹路径 从 负的屏幕 到当前屏幕 再到 超出的屏幕一个类似帧动画效果
  4. 添加多一个水纹面板 进行反向运动 看起来就像水波纹运动效果
//
//  Home.swift
//  Canvas (iOS)
//
//  Created by lyh on 2022/8/28.
//

import SwiftUI

struct Home: View {
    
    
    @State var toggle = false
    var body: some View {
    
    
        ZStack{
    
    
            // 波形视图…
            WaveForm(color: .cyan.opacity(0.8),amplify: 150,isReversed: false)
            
            
            WaveForm(color: toggle ? Color.purple : Color.cyan .opacity(0.6),amplify: 140,isReversed: true)

            VStack{
    
    
                HStack{
    
    
                    Text("Wave's")
                        .font(.largeTitle.bold())
                    Spacer()
                    
                    Toggle(isOn: $toggle) {
    
    
                        Image(systemName: "eyedropper.halffull")
                            .font(.title2)
                    }
                    .toggleStyle(.button)
                    .tint(.purple)
                }
                
            }
            .padding()
            .frame(maxHeight:.infinity,alignment: .top)
            
        }
        .ignoresSafeArea(.all,edges: .bottom)
    }
}

struct Home_Previews: PreviewProvider {
    
    
    static var previews: some View {
    
    
        ContentView()
    }
}

struct WaveForm : View{
    
    
    
    // 自定义颜色…
    var color : Color
    
    var amplify : CGFloat
    
    // 反向运动
    var isReversed : Bool
    
    var body: some View {
    
    
        // 使用时间线视图查看周期更新…
        TimelineView(.animation){
    
     timeLine in
            
            
            // 画布视图绘制波浪…
            Canvas{
    
     context,size in
                // 获得当前时间……
                let timeNow = timeLine.date.timeIntervalSinceReferenceDate
                
                // 使用当前时间动画波…
                let angle = timeNow.remainder(dividingBy: 2)
                
                // 计算偏移量……
                let offset = angle * size.width
                
                
                // 绘制文本 仅用来测试偏移量幅度
//                context.draw(Text("\(offset)"), at: CGPoint(x: size.width/2, y: 100))
                
                // 你可以看到它现在切换到屏幕宽度…

                
                // 你可以看到它在-1.5 -1.5 ....之间移动
                // ie 3/2 = 1.5
                // 如果2表示-1到1 .....
                
                // 移动整个视图…
                // 简单易行的波浪动画
                context.translateBy(x: isReversed ? -offset : offset, y: 0)
                
                // Using SwiftUI Path For darwing wave
                // 使用SwiftUI路径绘制波浪
                context.fill(getPath(size: size), with: .color(color))
                
                // darwing curve front and back
                // so that tranlation will be look like wave animation...
                //绘制前后曲线
                //这样翻译看起来就像波浪动画…
                context.translateBy(x: -size.width, y: 0)
                context.fill(getPath(size: size), with: .color(color))
                context.translateBy(x: size.width * 2, y: 0)
                context.fill(getPath(size: size), with: .color(color))
                
            }
            
        }
    }
    
    func getPath(size:CGSize)->Path{
    
    
        return Path{
    
    path in
            
            let midHeight = size.height / 2
            
            let width = size.width
            
            // 将波浪移动到中心,引导…

            path.move(to: CGPoint(x: 0, y: midHeight))
            
            // 画曲线……
            // 为底
            path.addCurve(to: CGPoint(x: width, y: midHeight), control1: CGPoint(x: width * 0.4, y: midHeight + amplify), control2: CGPoint(x: width * 0.65, y: midHeight - amplify))
            
            // 填充底部剩余区域…
            path.addLine(to: CGPoint(x: width, y: size.height))
            path.addLine(to: CGPoint(x: 0, y: size.height))

            
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42816425/article/details/126563807