无法在缩放的 ScrollView 中平移图像?
Cannot pan image in zoomed ScrollView?
我想构建一个简单的视图,允许我在滚动视图中显示图像并让用户捏合以缩放和平移图像。
我环顾四周并从这个开始ScrollView
:
struct TestView: View {
var body: some View {
ScrollView {
Image("test")
.border(Color(.yellow))
}
.border(Color(.red))
}
}
那不会处理缩放。
然后我这样做了:
struct TestView: View {
/// https://wp.usatodaysports.com/wp-content/uploads/sites/88/2014/03/sunset-in-the-dolos-mikadun.jpg
var image = UIImage(named: "test")!
@State var scale: CGFloat = 1.0
@State var lastScaleValue: CGFloat = 1.0
var body: some View {
GeometryReader { geo in
ScrollView([.vertical, .horizontal], showsIndicators: false){
ZStack{
Image(uiImage: image)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: geo.size.width, height: geo.size.width)
.scaleEffect(scale)
.gesture(MagnificationGesture().onChanged { val in
let delta = val / self.lastScaleValue
self.lastScaleValue = val
var newScale = self.scale * delta
if newScale < 1.0 {
newScale = 1.0
}
scale = newScale
}.onEnded{val in
lastScaleValue = 1
})
}
}
.frame(width: geo.size.width, height: geo.size.width)
.border(Color(.red))
.background(Color(.systemBackground).edgesIgnoringSafeArea(.all))
}
}
}
这允许我放大和缩小,但是我不能平移图像:
如何编写代码才能支持缩放和平移?
为了获得平移功能,您必须更改图像容器的大小,在本例中为 ZStack。
所以首先我们需要一个变量来保存当前最新的刻度值
@State var scaledFrame: CGFloat = 1.0
然后每次手势结束时改变容器的大小。
ZStack{
Image(uiImage: image)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: geo.size.width, height: geo.size.width )
.scaleEffect(scale)
.gesture(MagnificationGesture().onChanged { val in
let delta = val / self.lastScaleValue
self.lastScaleValue = val
var newScale = self.scale * delta
if newScale < 1.0 {
newScale = 1.0
}
scale = newScale
}.onEnded{val in
scaledFrame = scale//Update the value once the gesture is over
lastScaleValue = 1
})
.draggable()
}
.frame(width: geo.size.width * scaledFrame, height: geo.size.width * scaledFrame)
//change the size of the frame once the drag is complete
这是由于 ScrollView 的工作方式,当您放大时,容器的实际大小并没有改变,因此 ScrollView 只是相应地移动。
我想构建一个简单的视图,允许我在滚动视图中显示图像并让用户捏合以缩放和平移图像。
我环顾四周并从这个开始ScrollView
:
struct TestView: View {
var body: some View {
ScrollView {
Image("test")
.border(Color(.yellow))
}
.border(Color(.red))
}
}
那不会处理缩放。
然后我这样做了:
struct TestView: View {
/// https://wp.usatodaysports.com/wp-content/uploads/sites/88/2014/03/sunset-in-the-dolos-mikadun.jpg
var image = UIImage(named: "test")!
@State var scale: CGFloat = 1.0
@State var lastScaleValue: CGFloat = 1.0
var body: some View {
GeometryReader { geo in
ScrollView([.vertical, .horizontal], showsIndicators: false){
ZStack{
Image(uiImage: image)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: geo.size.width, height: geo.size.width)
.scaleEffect(scale)
.gesture(MagnificationGesture().onChanged { val in
let delta = val / self.lastScaleValue
self.lastScaleValue = val
var newScale = self.scale * delta
if newScale < 1.0 {
newScale = 1.0
}
scale = newScale
}.onEnded{val in
lastScaleValue = 1
})
}
}
.frame(width: geo.size.width, height: geo.size.width)
.border(Color(.red))
.background(Color(.systemBackground).edgesIgnoringSafeArea(.all))
}
}
}
这允许我放大和缩小,但是我不能平移图像:
如何编写代码才能支持缩放和平移?
为了获得平移功能,您必须更改图像容器的大小,在本例中为 ZStack。 所以首先我们需要一个变量来保存当前最新的刻度值
@State var scaledFrame: CGFloat = 1.0
然后每次手势结束时改变容器的大小。
ZStack{
Image(uiImage: image)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: geo.size.width, height: geo.size.width )
.scaleEffect(scale)
.gesture(MagnificationGesture().onChanged { val in
let delta = val / self.lastScaleValue
self.lastScaleValue = val
var newScale = self.scale * delta
if newScale < 1.0 {
newScale = 1.0
}
scale = newScale
}.onEnded{val in
scaledFrame = scale//Update the value once the gesture is over
lastScaleValue = 1
})
.draggable()
}
.frame(width: geo.size.width * scaledFrame, height: geo.size.width * scaledFrame)
//change the size of the frame once the drag is complete
这是由于 ScrollView 的工作方式,当您放大时,容器的实际大小并没有改变,因此 ScrollView 只是相应地移动。