SwiftUI 中的锚点
Anchor point in SwiftUI
我正在玩 SwiftUI
动画。我想让一个正方形变大,这样用动画修改它的框架:
struct ContentView: View {
let squareWidth = CGFloat(100)
let squareHeight = CGFloat(100)
@State private var bigger = false
var body: some View {
VStack {
Color.green
.frame(width: bigger ? self.squareWidth * 2 : self.squareWidth, height: self.squareHeight)
.animation(.default)
Button(action: {
self.bigger.toggle()
}) {
Text("Click me!")
}
}
}
}
动画发生在视图的中心,即锚点 (0.5, 0.5)。有没有办法改变这个锚点?我发现我可以在指定 anchor
:
的视图上使用 scaleEffect
struct ContentView: View {
let squareWidth = CGFloat(100)
let squareHeight = CGFloat(100)
@State private var bigger = false
var body: some View {
VStack {
Color.green
.frame(width: self.squareWidth, height: self.squareHeight)
.scaleEffect(x: bigger ? 2 : 1, y: 1, anchor: .leading)
.animation(.default)
Button(action: {
self.bigger.toggle()
}) {
Text("Click me!")
}
}
}
}
但好像不完全一样。如果我需要应用多个效果,我应该为每个效果指定锚点,而不是只在视图上指定一次锚点。在 UIKit
我可以写:
var myView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
myView.layer.anchorPoint = CGPoint(x: 0, y: 0.5) //that is, the .leading of SwiftUI
这是可能的,但你的方法必须改变。
SwiftUI 中有一个隐含的内置视图居中,这可能会造成混淆。
父视图是将内容放置在中心的视图,每次子视图的框架改变时重新计算其位置。
将 VStack 嵌入 HStack 并为两者添加边框清楚地显示了这种行为。
另外,请注意 Spacer()
,它将视图向左推。
HStack {
VStack {
Color.green
.frame(width: bigger ? self.squareWidth * 2 : self.squareWidth)
.frame(height: self.squareHeight)
.animation(.default)
Button("Click me!") { self.bigger.toggle() }
}.border(Color.black)
Spacer()
}.border(Color.red)
在 UIKit 中使用 .layer.anchorPoint
应该与在 SwiftUI 中使用 scaleEffect/offset/rotationEffect 具有相同的效果,因为它会影响由 GPU 渲染的底层 geometry/texture 的来源.
如果您有一个复杂的视图(由多个子视图组成)需要相同的缩放效果,您可以使用 Group { }
对它们进行分组并对其使用 .scaleEffect。
我正在玩 SwiftUI
动画。我想让一个正方形变大,这样用动画修改它的框架:
struct ContentView: View {
let squareWidth = CGFloat(100)
let squareHeight = CGFloat(100)
@State private var bigger = false
var body: some View {
VStack {
Color.green
.frame(width: bigger ? self.squareWidth * 2 : self.squareWidth, height: self.squareHeight)
.animation(.default)
Button(action: {
self.bigger.toggle()
}) {
Text("Click me!")
}
}
}
}
动画发生在视图的中心,即锚点 (0.5, 0.5)。有没有办法改变这个锚点?我发现我可以在指定 anchor
:
scaleEffect
struct ContentView: View {
let squareWidth = CGFloat(100)
let squareHeight = CGFloat(100)
@State private var bigger = false
var body: some View {
VStack {
Color.green
.frame(width: self.squareWidth, height: self.squareHeight)
.scaleEffect(x: bigger ? 2 : 1, y: 1, anchor: .leading)
.animation(.default)
Button(action: {
self.bigger.toggle()
}) {
Text("Click me!")
}
}
}
}
但好像不完全一样。如果我需要应用多个效果,我应该为每个效果指定锚点,而不是只在视图上指定一次锚点。在 UIKit
我可以写:
var myView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
myView.layer.anchorPoint = CGPoint(x: 0, y: 0.5) //that is, the .leading of SwiftUI
这是可能的,但你的方法必须改变。
SwiftUI 中有一个隐含的内置视图居中,这可能会造成混淆。
父视图是将内容放置在中心的视图,每次子视图的框架改变时重新计算其位置。
将 VStack 嵌入 HStack 并为两者添加边框清楚地显示了这种行为。
另外,请注意 Spacer()
,它将视图向左推。
HStack {
VStack {
Color.green
.frame(width: bigger ? self.squareWidth * 2 : self.squareWidth)
.frame(height: self.squareHeight)
.animation(.default)
Button("Click me!") { self.bigger.toggle() }
}.border(Color.black)
Spacer()
}.border(Color.red)
在 UIKit 中使用 .layer.anchorPoint
应该与在 SwiftUI 中使用 scaleEffect/offset/rotationEffect 具有相同的效果,因为它会影响由 GPU 渲染的底层 geometry/texture 的来源.
如果您有一个复杂的视图(由多个子视图组成)需要相同的缩放效果,您可以使用 Group { }
对它们进行分组并对其使用 .scaleEffect。