传统的七夕快到了,作为一个程序猿,最浪漫的礼物当然是自己写的啦!
思来想去也不知道写什么好,在某天在某音上学习时看到点赞的动画效果还不错,那不如就做一个表达爱意的动画吧。
说干就干。
项目搭建
首先,创建一个新的SwiftUI
项目,命名为LoveAnimation
。
逻辑分析
我们先分析下整个点赞效果的逻辑,当我们点击“白色爱心”时,会冒出很多“红色爱心”出来,并且呈现的效果是出现后向上随机散开后消失。
如果我们需要实现这个效果,那么不妨设想下实现过程,先有一个“白色爱心”,然后使用ZStack
层叠视图覆盖一层“红色爱心”,当点击“白色爱心”时触发交互动画,“红色爱心”在出现时增加交互效果,实现向上随机散开后消失。
页面样式
页面样式部分,我们可以创建两个心形视图。示例:
struct ContentView: View { @State var loveCount = 0 func TapAction() { loveCount += 1 } var body: some View { ZStack { Color.black.ignoresSafeArea() VStack(alignment: .center, spacing: 40) { ZStack { Image(systemName: "heart.fill") .resizable() .foregroundColor(.white) .frame(width: 120, height: 120) .padding() .onTapGesture { TapAction() } ForEach(0 ..< loveCount, id: \.self) { _ in Image(systemName: "heart.fill") .resizable() .frame(width: 120, height: 120) .padding() } } Text("我喜欢你") .font(.largeTitle) .foregroundColor(.white) } } } } 复制代码
上述代码中,我们声明了一个变量loveCount
来存储心形的数量,然后定义了一个方法TapAction
,当我们点击的时候,loveCount
心形数量增加。
样式部分我们将背景变成黑色,然后绘制了一个白色的心形,再使用ZStack
包裹了一个红色的心形,当白色的心形点击时,调用TapAction
方法。
初步的样式就完成了。
动画逻辑
页面比较简单,我们接下来完成动画逻辑部分。
import SwiftUI struct LoveGeometryEffect : GeometryEffect { var time : Double var speed = Double.random(in: 100 ... 200) var xDirection = Double.random(in: -0.1 ... 0.1) var yDirection = Double.random(in: -Double.pi ... 0) var animatableData: Double { get { time } set { time = newValue } } func effectValue(size: CGSize) -> ProjectionTransform { let xTranslation = speed * xDirection let yTranslation = speed * sin(yDirection) * time let affineTranslation = CGAffineTransform(translationX: xTranslation, y: yTranslation) return ProjectionTransform(affineTranslation) } } 复制代码
上述代码中,我们创建了一个爱心动画LoveGeometryEffect
,它遵循GeometryEffect
协议。
我们首先声明了4个变量,分别是时间time、速度speed、X轴出现的位置xDirection,Y轴出现的位置yDirection。
其中,speed、xDirection、yDirection
都使用随机数,这样我们就能实现线性出现的效果,不至于那么死板。
然后使用get、set
属性,在获得time
初始值时,调用了get
属性计算出的新值。
最后我们定义了一个方法effectValue
返回一个ProjectionTransform
投影转换效果,来实现红色爱心的移动效果。
视图修饰符
有了交互动画逻辑后,我们可以创建一个视图修饰符,用于之后修饰我们的红色爱心视图。示例:
import SwiftUI struct LoveTapModifier: ViewModifier { @State var time = 0.0 let duration = 1.0 func body(content: Content) -> some View { ZStack { content .foregroundColor(.red) .modifier(LoveGeometryEffect(time: time)) .opacity(time == 1 ? 0 : 1) } .onAppear { withAnimation (.easeOut(duration: duration)) { self.time = duration } } } } 复制代码
上述代码中,我们创建了一个视图修饰LoveTapModifier
,它的内容包含设置视图的填充色为红色,并使用之前创建好的LoveGeometryEffect
动画进行修饰。
为了让红色爱心出现后跟随时间逐渐消失,我们使用opacity
修饰符,让视图跟随时间慢慢隐藏。
效果呈现
完成后,我们将LoveTapModifier
修饰符作用在红色心形视图上。示例:
.modifier(LoveTapModifier()) 复制代码
不错不错!
赶紧发给喜欢的女生,收一张好人卡先。