技术:SwiftUI、SwiftUI3.0、水波纹、动画、水波纹动画
运行环境:
SwiftUI3.0 + Xcode13.4.1 + MacOS12.5 + iPhone Simulator iPhone 13 Pro Max
SwiftUI搭建一个水波纹动画效果
概述
使用SwiftUI搭建一个水波纹动画效果
详细
一、运行效果
二、项目结构图
三、程序实现 - 过程
思路:
- 先通过Canvas画出波浪形状
- 填充底部颜色
- 使用
TimelineView
时间视图 进行一个类似帧动画的渲染 。渲染的返回就是当前水纹路径 从 负的屏幕 到当前屏幕 再到 超出的屏幕一个类似帧动画效果- 添加多一个水纹面板 进行反向运动 看起来就像水波纹运动效果
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 - 主页
思路
- 先通过Canvas画出波浪形状
- 填充底部颜色
- 使用
TimelineView
时间视图 进行一个类似帧动画的渲染 。渲染的返回就是当前水纹路径 从 负的屏幕 到当前屏幕 再到 超出的屏幕一个类似帧动画效果- 添加多一个水纹面板 进行反向运动 看起来就像水波纹运动效果
//
// 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))
}
}
}