【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

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

扫描二维码关注公众号,回复: 14508918 查看本文章

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
今日推荐