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

如何用多个重叠矩形实现反向遮罩(消除交叉填充问题)

解决方案

要实现原矩形完全移除所有动态生成的遮罩矩形区域(包括交叉部分),可以通过以下两种方式实现,均适配macOS 11.3部署目标:

方法一:使用Path的subtracting(_:)方法(推荐)

该方法直接将原路径与每个要移除的矩形路径执行差集运算,最终得到原矩形减去所有遮罩矩形并集的路径,完全符合需求。

修改后的代码

struct MyShape: Shape {
    let originalRect: CGRect
    let rectsToRemove: [CGRect]
    
    func path(in rect: CGRect) -> Path {
        var resultPath = Path(originalRect)
        // 逐个减去所有要移除的矩形路径
        for removeRect in rectsToRemove {
            resultPath = resultPath.subtracting(Path(removeRect))
        }
        return resultPath
    }
}

struct ContentView: View {
    var body: some View {
        let originalRect = CGRect(x: 0, y: 0, width: 400, height: 300)
        // 动态生成的待移除矩形数组
        let rectsToRemove = [
            CGRect(x: 60, y: 60, width: 100, height: 100),
            CGRect(x: 120, y: 120, width: 100, height: 100),
            CGRect(x: 0, y: 0, width: 100, height: 100)
        ]
        
        ZStack {
            Color.red
                .mask(MyShape(originalRect: originalRect, rectsToRemove: rectsToRemove))
        }
        .frame(width: 400, height: 300)
    }
}

方法二:利用路径方向与非零缠绕数填充规则

默认的填充规则(eoFill: false)是非零缠绕数规则,通过反转待移除矩形的路径方向(与原矩形路径方向相反),可以让遮罩区域的缠绕数归0,从而被排除在填充范围外,解决evenOdd规则下交叉区域被重新填充的问题。

修改后的代码

struct MyShape: Shape {
    func path(in rect: CGRect) -> Path {
        var p = Path()
        // 添加原矩形(默认顺时针方向)
        p.addRect(rect)
        
        // 添加反转方向的待移除矩形(逆时针)
        p.addPath(Path(CGRect(x: 60, y: 60, width: 100, height: 100)).reversed())
        p.addPath(Path(CGRect(x: 120, y: 120, width: 100, height: 100)).reversed())
        p.addPath(Path(CGRect(x: 0, y: 0, width: 100, height: 100)).reversed())
        
        return p
    }
}

struct ContentView: View {
    var body: some View {
        ZStack {
            Color.red
                .mask(
                    MyShape()
                        .fill(style: .init(eoFill: false)) // 使用默认非零缠绕数规则
                )
        }
        .frame(width: 400, height: 300)
    }
}

为什么evenOdd规则会出现交叉区域填充问题

evenOdd规则是根据路径覆盖区域的重叠次数判断:奇数次重叠保留,偶数次重叠剔除。当多个遮罩矩形交叉时,交叉区域的重叠次数为偶数,因此会被重新填充,不符合你需要完全移除所有遮罩区域的需求。而上述两种方法都能确保所有被遮罩矩形覆盖的区域(无论重叠次数)都被完全移除。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 04:15:48