如何检测两个 CAShapeLayers 何时相交并更改相交像素的颜色

How to detect when two CAShapeLayers intersect and to change the color of the intersecting pixels

提问人:Ser Pounce 提问时间:6/28/2023 最后编辑:Ser Pounce 更新时间:7/1/2023 访问量:59

问:

我有一个名为 which subclasses 的类。在这个类中,有一个属性,我用它来定义各种类型的复杂形状。使用 ,ShapeView 将转换为 ,然后将其设置为 image 属性。ShapeViewUIImageViewCALayershapeUIGraphicsBeginImageContextWithOptionsshapeUIImageUIImageView's

使用此设置,我想合并两个相互相交的形状,如下所示:

enter image description here

enter image description here

如您所见,我正在设置每个形状的 stroke 属性,以便每个形状都有一个黑色边框。我想让它,如果两个形状相互相交,我可以检测到另一个形状内部的笔触部分,并更改这些像素的颜色,以便给人一种两个形状正在合并的印象。CAShapeLayerUIClearColor

不过,对于如何检测已转换为 a 的某个区域是否在另一个也已转换为 .以及如何将这些精确像素的颜色更改为(这甚至可能吗?CAShapeLayerUIImageCAShapeLayerUIImageUIClearColor

谢谢!

iOS Objective-C UIImiveView UIImiveView 核心图形

评论

1赞 DonMag 6/28/2023
“......子类 UIImageView“ -- 这些自定义视图是否也具有(其他)图像?如果不是,您从形状图层生成是有原因的吗?“......各种类型的复杂形状“——我认为你需要展示一些复杂的形状示例,并阐明你希望结果是什么样子。例如,做这里的两个例子(imgur.com/a/JuVLotk)是一件相当简单的任务。UIImage
0赞 Ser Pounce 6/29/2023
@DonMag 谢谢,你提到生成 UIImages 的事情很有趣,因为我一直在考虑只使用 CAShapeLayers。在某些情况下,此类将仅使用用户定义的 UIImage 而不是 CAShapeLayer,因此我希望能够适应这两种情况,但我想我可以以某种方式将该 UIImage 转换为 CAShapeLayer?关于复杂的形状,它们可能比正方形或圆形有更多的边,但没有什么太疯狂的。结果不一定是你链接到的内容,只要希望它们在用户移动在一起时相交。
0赞 DonMag 6/29/2023
仍然需要澄清你真正想做什么。我在这里添加了两个带有“形状”的变体:imgur.com/a/JuVLotk ...这看起来和你的目标相似吗?
0赞 Ser Pounce 6/29/2023
@DonMag 感谢您所做的一切,是的,除了带有图像的那些之外,这是正确的。当这个类使用图像时,它只是图像本身(没有形状或笔触),它不必做我想要的合并事情,将是完全独立的。但是其他形状合并的,这是完全正确的。
0赞 DonMag 7/1/2023
“当这个类使用图像时......”——对不起,这让我感到困惑。我使用路径方法发布了一个答案。希望它能帮助你。

答:

3赞 DonMag 7/1/2023 #1

我真的不明白你想用图像做什么......但让我们看一下路径选项(而不是从每个路径/形状生成一个)。UIImage

如果您的目标是,我们可以利用 CGPathCreateCopyByUnioningPath(对于以前的 iOS 版本,您可以在那里找到一些 Bezier Path 库)。iOS 16.0+

简单描述...

假设我们用这些分隔的矩形创建两个矩形路径:

CGRect r1 = CGRectMake(60, 20, 100, 100);
CGRect r2 = CGRectMake(200, 60, 100, 100);

CGPathRef pthA = CGPathCreateWithRect(r1, nil);
CGPathRef pthB = CGPathCreateWithRect(r2, nil);

如果我们随后将这些路径添加到可变路径中:

CGMutablePathRef pth = CGPathCreateMutable();
CGPathAddPath(pth, nil, pthA);
CGPathAddPath(pth, nil, pthB);

shapeLayer.path = pth;

我们得到这个:

enter image description here

现在让我们更改矩形,使它们重叠:

CGRect r1 = CGRectMake(100, 20, 100, 100);
CGRect r2 = CGRectMake(160, 60, 100, 100);

CGPathRef pthA = CGPathCreateWithRect(r1, nil);
CGPathRef pthB = CGPathCreateWithRect(r2, nil);

CGMutablePathRef pth = CGPathCreateMutable();
CGPathAddPath(pth, nil, pthA);
CGPathAddPath(pth, nil, pthB);

shapeLayer.path = pth;

我们得到这个结果:

enter image description here

由于您的目标是“删除重叠的线”,因此我们可以使用...与上述相同的重叠矩形:CGPathCreateCopyByUnioningPath

CGRect r1 = CGRectMake(100, 20, 100, 100);
CGRect r2 = CGRectMake(160, 60, 100, 100);

CGPathRef pthA = CGPathCreateWithRect(r1, nil);
CGPathRef pthB = CGPathCreateWithRect(r2, nil);

CGPathRef pth = CGPathCreateCopyByUnioningPath(pthA, pthB, NO);

shapeLayer.path = pth;

现在我们得到这个作为输出:

enter image description here

我在这里发布了一个示例项目: https://github.com/DonMag/CGPathUnion

enter image description here

enter image description here

评论

0赞 Ser Pounce 7/2/2023
这太棒了,非常感谢。