You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用SwiftUI实现拖动上层抠图照片下方的背景图片

问题解决方法

核心原因是ZStack中上层的抠图图像默认会接收所有触控事件,拦截了下层背景图层的手势响应,按以下步骤修改即可:

  • 给上层的抠图图像添加allowsHitTesting(false)修饰符,禁用它的触控事件接收能力,触控事件就会透传到下层的背景图层
  • 你现有代码里的DragGesture存在冗余逻辑,updating回调仅用来更新@GestureState属性即可,不要直接修改@State变量,位置更新逻辑放到onChanged里就足够了
  • 额外清理了原代码中未使用的冗余currentPositions变量
修改后的完整代码
struct MaskImage: View {
  @State var currentPosition = CGPoint.init(x: UIScreen.main.bounds.width/2, y: UIScreen.main.bounds.height/4)
  @GestureState private var isDragging = false
  
  var body: some View {
    GeometryReader { geo in
      HStack {
        VStack {
          Spacer()
          
          ZStack {
              // 可拖动的背景图
              Image("EFFECT-1")
                .resizable()
                .frame(width: abs(geo.size.width-32), height: 375, alignment: .center)
                .position(currentPosition)
                .gesture(
                  DragGesture()
                    .onChanged { value in
                      self.currentPosition = value.location
                    }
                    .updating($isDragging) { (value, state, transaction) in
                      state = true
                    }
                )
            
              // 上层抠图前景
              Image("SEGMENTED_IMAGE_REMOVE_BACKGROUND")
                .resizable()
                .frame(width: abs(geo.size.width - 32), height: abs(round((geo.size.width / 2) * 2.438)), alignment: .center)
                // 禁用触控事件接收,让手势透传到下层
                .allowsHitTesting(false)
          }
          
          Spacer()
        }
      }
      .background(Color.red)
    }
  }
}
补充说明

如果后续需要给前景抠图也加手势操作(比如调整大小、移动前景),可以不用加allowsHitTesting,改为把拖动手势加到ZStack本身上,再根据当前选中的编辑对象(背景/前景)分别更新对应的位置参数即可。

内容的提问来源于stack exchange,提问作者Ifadak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 06:48:03