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

iOS Swift:贝塞尔路径擦除区域添加可拖拽缩放矩形图像框实现咨询

Swift iOS 实现可拖拽调整的遮罩式图像替换功能

1. 实现可调整大小的矩形框加载新图像

我们可以自定义一个支持平移、缩放的UIImageView子类,通过手势识别器实现拖拽和调整大小功能:

自定义可调整图像视图

import UIKit

class ResizableImageView: UIImageView {
    private let panGesture = UIPanGestureRecognizer()
    private let pinchGesture = UIPinchGestureRecognizer()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupBaseConfig()
        setupGestures()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupBaseConfig()
        setupGestures()
    }
    
    private func setupBaseConfig() {
        borderColor = .blue
        borderWidth = 2
        isUserInteractionEnabled = true
        contentMode = .scaleAspectFit
    }
    
    private func setupGestures() {
        panGesture.addTarget(self, action: #selector(handlePan(_:)))
        pinchGesture.addTarget(self, action: #selector(handlePinch(_:)))
        
        addGestureRecognizer(panGesture)
        addGestureRecognizer(pinchGesture)
        panGesture.require(toFail: pinchGesture)
    }
    
    @objc private func handlePan(_ gesture: UIPanGestureRecognizer) {
        let translation = gesture.translation(in: superview)
        center = CGPoint(x: center.x + translation.x, y: center.y + translation.y)
        gesture.setTranslation(.zero, in: superview)
    }
    
    @objc private func handlePinch(_ gesture: UIPinchGestureRecognizer) {
        transform = transform.scaledBy(x: gesture.scale, y: gesture.scale)
        gesture.scale = 1.0
    }
}

在视图控制器中初始化并加载图像

// 假设你已存在擦除操作后的主图像视图mainImageView
let resizableImageFrame = CGRect(x: 100, y: 100, width: 200, height: 200)
let resizableImageView = ResizableImageView(frame: resizableImageFrame)
resizableImageView.image = UIImage(named: "your_new_image")
view.addSubview(resizableImageView)

2. 仅显示矩形框与擦除路径的重叠区域

通过CAShapeLayer做遮罩,利用路径的奇偶填充规则实现仅显示矩形框和擦除路径的交集区域:

修改自定义视图添加遮罩逻辑

class ResizableImageView: UIImageView {
    // 接收外部传入的擦除路径
    var erasedPath: UIBezierPath? {
        didSet {
            updateMaskLayer()
        }
    }
    private let maskLayer = CAShapeLayer()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupBaseConfig()
        setupGestures()
        layer.mask = maskLayer
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupBaseConfig()
        setupGestures()
        layer.mask = maskLayer
    }
    
    // ... 保留之前的setupBaseConfig、手势处理代码
    
    private func updateMaskLayer() {
        guard let erasedPath = erasedPath else { return }
        
        // 创建当前视图的矩形路径
        let rectPath = UIBezierPath(rect: bounds)
        // 合并路径并启用奇偶填充规则
        rectPath.append(erasedPath)
        rectPath.usesEvenOddFillRule = true
        
        maskLayer.path = rectPath.cgPath
        maskLayer.fillRule = .evenOdd
    }
    
    // 更新手势处理,实时刷新遮罩
    @objc private func handlePan(_ gesture: UIPanGestureRecognizer) {
        let translation = gesture.translation(in: superview)
        center = CGPoint(x: center.x + translation.x, y: center.y + translation.y)
        gesture.setTranslation(.zero, in: superview)
        updateMaskLayer()
    }
    
    @objc private func handlePinch(_ gesture: UIPinchGestureRecognizer) {
        transform = transform.scaledBy(x: gesture.scale, y: gesture.scale)
        gesture.scale = 1.0
        updateMaskLayer()
    }
    
    // 视图frame变化时同步更新遮罩
    override func layoutSubviews() {
        super.layoutSubviews()
        updateMaskLayer()
    }
}

传入擦除路径

// 假设erasedPath是用户绘制并保存的贝塞尔路径
// 注意:如果主图像视图有缩放/平移,需转换路径坐标系匹配当前视图
let transformedErasedPath = erasedPath.copy() as! UIBezierPath
transformedErasedPath.apply(mainImageView.transform)

resizableImageView.erasedPath = transformedErasedPath

额外说明

  • 如果需要支持拖动边角精确调整大小,可以添加自定义拖拽手柄(如四个小UIView)并绑定长按手势实现。
  • 确保路径坐标系统一,否则遮罩区域会出现偏移。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 04:41:16