将多个 CGPath 合并为一个路径

Posted

技术标签:

【中文标题】将多个 CGPath 合并为一个路径【英文标题】:Merge multiple CGPaths together to make one path 【发布时间】:2013-07-09 03:28:07 【问题描述】:

我正在使用一些 CGRects 和 Ellipses 制作一个复杂的形状。一旦它被创建,我想抚摸这条路径。当我抚摸路径时,它会抚摸每个形状。有没有办法可以将每个形状合并成一条路径,这样笔划就不会相交?

int thirds = self.height / 3;

CGPathRef aPath = CGPathCreateMutable();

CGRect rectangle = CGRectMake((58 - 10) / 2, 46, 10, self.height - 58);
CGPathAddRect(aPath, nil, rectangle);

CGPathAddEllipseInRect(aPath, nil, CGRectMake((58 - 48) / 2, 0, 48, 48));
CGPathAddEllipseInRect(aPath, nil, CGRectMake((58 - 48) / 2, thirds, 48, 48));
CGPathAddEllipseInRect(aPath, nil, CGRectMake((58 - 48) / 2, thirds * 2, 48, 48));
CGPathAddEllipseInRect(aPath, nil, CGRectMake(0, self.height - 58, 58, 58));
CGPathCloseSubpath(aPath);
CGPathRef other = CGPathCreateCopy(aPath);

CAShapeLayer *square = [CAShapeLayer layer];
square.fillColor = [UIColor colorWithRed:36/255.0f green:56/255.0f blue:82/255.0f alpha:1.0f].CGColor;
square.strokeColor = [UIColor colorWithRed:50/255.0f green:70/255.0f blue:96/255.0f alpha:1.0f].CGColor;
square.path = other;
[self.layer addSublayer:square];

更新

我尝试将路径添加在一起,得到了完全相同的结果

CGPathAddPath(aPath, nil, CGPathCreateWithRect(rectangle, nil));

CGPathAddPath(aPath, nil, CGPathCreateWithEllipseInRect(CGRectMake((58 - 48) / 2, 0, 48, 48), nil));
CGPathAddPath(aPath, nil, CGPathCreateWithEllipseInRect(CGRectMake((58 - 48) / 2, thirds, 48, 48), nil));
CGPathAddPath(aPath, nil, CGPathCreateWithEllipseInRect(CGRectMake((58 - 48) / 2, thirds * 2, 48, 48), nil));
CGPathAddPath(aPath, nil, CGPathCreateWithEllipseInRect(CGRectMake(0, self.height - 58, 58, 58), nil));

【问题讨论】:

CGPathAddPath(path1, NULL, path2) @CodaFi 所以为每个形状创建一个新路径并使用CGPathAddPath? 【参考方案1】:

如果您想要一个仅描述路径组合轮廓的路径,则需要对参与的形状执行布尔运算。 那里有一些很好的教程。 例如。: http://losingfight.com/blog/2011/07/07/how-to-implement-boolean-operations-on-bezier-paths-part-1/

如果你只是想实现轮廓的视觉外观,你可以画2个形状层:

填充通过 CGPathCreateCopyByStrokingPath 获得的路径和 填满原始路径的顶部

使用您发布的代码中的形状:

int thirds = self.height / 3;

CGMutablePathRef aPath = CGPathCreateMutable();

CGRect rectangle = CGRectMake((58 - 10) / 2, 46, 10, self.height - 58);
CGPathAddRect(aPath, nil, rectangle);

CGPathAddEllipseInRect(aPath, nil, CGRectMake((58 - 48) / 2, 0, 48, 48));
CGPathAddEllipseInRect(aPath, nil, CGRectMake((58 - 48) / 2, thirds, 48, 48));
CGPathAddEllipseInRect(aPath, nil, CGRectMake((58 - 48) / 2, thirds * 2, 48, 48));
CGPathAddEllipseInRect(aPath, nil, CGRectMake(0, self.height - 58, 58, 58));
CGPathCloseSubpath(aPath);

CGPathRef other = CGPathCreateCopyByStrokingPath(aPath, NULL, 12.0, kCGLineCapRound, kCGLineJoinRound, 1.0);
CAShapeLayer *square = [CAShapeLayer layer];
square.fillColor = [UIColor colorWithRed:36/255.0f green:56/255.0f blue:82/255.0f alpha:1.0f].CGColor;
square.path = other;
[self.view.layer addSublayer:square];

CAShapeLayer *square2 = [CAShapeLayer layer];
square2.fillColor = [UIColor colorWithRed:50/255.0f green:70/255.0f blue:96/255.0f alpha:1.0f].CGColor;
square2.path = aPath;
[self.view.layer addSublayer:square2];

这将绘制以下形状:

【讨论】:

您先生是个天才和学者。谢谢你的解释。【参考方案2】:

基于 Thomas Zoechling 的回答

对于 swift3

height = self.bounds.size.height
let thirds = self.height / 3

let aPath: CGMutablePath = CGMutablePath()
let rect = CGRect(x: (58 - 10) / 2, y: 46, width: 10, height: self.height - 58)
aPath.addRect(rect)

aPath.addEllipse(in: CGRect(x: (58 - 48) / 2, y: 0, width: 48, height: 48))
aPath.addEllipse(in: CGRect(x: (58 - 48) / 2, y: thirds, width: 48, height: 48))
aPath.addEllipse(in: CGRect(x: (58 - 48) / 2, y: thirds * 2, width: 48, height: 48))
aPath.addEllipse(in: CGRect(x: 0, y: self.height, width: 48, height: 48))
aPath.closeSubpath()

let other: CGPath = aPath.copy(strokingWithWidth: 12, lineCap: .round, lineJoin: .round, miterLimit: 1.0)
let square = CAShapeLayer()
square.fillColor = UIColor(red: 36/255.0, green: 56/255.0, blue: 82/255.0, alpha: 1.0).cgColor
square.path = other
self.layer.addSublayer(square)

let square2 = CAShapeLayer()
square2.fillColor = UIColor(red: 50/255.0, green: 70/255.0, blue: 96/255.0, alpha: 1.0).cgColor
square2.path = aPath
self.layer.addSublayer(square2)

【讨论】:

以上是关于将多个 CGPath 合并为一个路径的主要内容,如果未能解决你的问题,请参考以下文章

在不裁剪的情况下填充 CGPath 的倒数

如何创建一个随机封闭平滑CGPath?

如何使 CAGradientLayer 遵循 CGPath

在 cgPath 上的两个坐标之间添加中点

带有 CGPath 的 UIView 和另一个包含第一个 UIView 的 UIView。如何将第一个视图放入第二个视图?

在不从 CGPath 开头开始的情况下跟随带有 SKAction 的 CGPath