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
相关产品推荐
相关产品推荐

