SwiftUI中点击正方形图片获取相对坐标异常问题求助
SwiftUI图片点击坐标异常与拖拽越界问题修复
问题根源
- X坐标计算错误:你用了外层
GeometryReader的size.width作为分母,但这个GeometryReader的宽度是父容器的宽度(远大于图片实际显示宽度),导致计算出的相对X值偏小。 - 拖拽触发区域外事件:
DragGesture(minimumDistance: 0)会识别整个拖拽路径,当拖拽到图片外时,value.location会指向图片外的坐标,从而触发异常事件。
修复方案
1. 正确获取图片实际显示尺寸计算相对坐标
将GeometryReader嵌套在Image的背景中,直接获取图片自身的显示frame,而非外层容器的尺寸。这样计算出的相对坐标才是基于图片实际大小的。
2. 替换为TapGesture(更适合点击场景)
如果你的需求只是点击获取坐标,TapGesture比DragGesture更合适,它只会响应图片范围内的点击事件,不会触发拖拽越界的问题。如果需要支持拖拽标记位置,可以保留DragGesture但添加坐标校验逻辑。
修复后的完整代码
import SwiftUI struct PositionsDetailsView: View { let match: Match @Binding var selectedPosition: (x: CGFloat, y: CGFloat)? var player: Player @Environment(\.presentationMode) var presentationMode @State private var tappedPosition: CGPoint? = nil @State private var imageSize: CGSize = .zero var body: some View { VStack { Text("Tik op de afbeelding om coördinaten te krijgen") .padding() GeometryReader { outerGeo in Image("half_korfbal_veld") .resizable() .scaledToFit() .overlay( tappedPosition.map { position in Circle() .fill(Color.red) .frame(width: 10, height: 10) .position(position) } ) .background( GeometryReader { imageGeo in Color.clear .onAppear { // 获取图片实际显示的尺寸 imageSize = imageGeo.size } } ) .gesture( TapGesture() .onEnded { location in // 基于图片实际尺寸计算相对坐标 let relativeX = location.x / imageSize.width let relativeY = location.y / imageSize.height tappedPosition = location selectedPosition = (x: relativeX, y: relativeY) print("图片实际宽高: \(imageSize.width) x \(imageSize.height)") print("相对坐标: (\(relativeX), \(relativeY))") } ) } .frame(height: 300) Button("Sluiten") { presentationMode.wrappedValue.dismiss() } .padding() } .padding() } }
额外优化说明
- 如果需要支持拖拽标记位置,保留
DragGesture但添加坐标校验:DragGesture(minimumDistance: 0) .onEnded { value in // 校验坐标是否在图片范围内 guard value.location.x >= 0, value.location.x <= imageSize.width, value.location.y >= 0, value.location.y <= imageSize.height else { return // 忽略图片外的拖拽事件 } let relativeX = value.location.x / imageSize.width let relativeY = value.location.y / imageSize.height tappedPosition = value.location selectedPosition = (x: relativeX, y: relativeY) } - 确保
Image的scaledToFit()正确保持正方形比例,外层frame(height:300)会让图片宽度自适应,保持2010×2010的原始比例。
内容的提问来源于stack exchange,提问作者KaiHoogenhoud
相关产品推荐
相关产品推荐

