如何在 UIBezierPath 的路径内部描边?

5

通常,在CoreGraphics中绘制贝塞尔路径时,我们可以使用“CGContextSetLineWidth”设置路径的所需粗细,它会在路径的外边界上描边(随着线条宽度的增加,边界似乎会向路径的外部扩展)。我希望我的线条粗细能够在贝塞尔路径内部增长,有没有办法实现这个效果?


可能是UIView drawRect: is it possible to stroke inside a path?的重复问题。 - Kurt Revis
1个回答

7
我不知道如何描绘路径的内部。但是,您可以完成类似的操作,这可能适合您。如果您缩小路径并将其移动到正确位置的中心,则它将完美地适合您想要的边界内。对于简单形状(如矩形、圆角矩形和椭圆形),在内部绘制和缩放之间的视觉差异不存在,但对于更复杂的形状则会有所不同。考虑一下如果使用“内部描边”描绘字母B与缩放的区别。
以下是使用非常宽的线条进行转换前后的样子。正如您所看到的,描绘线条将使其居中于路径上,使其一半出现在每侧。因此,为了进行转换,我们需要将路径向下和向右移动半个线宽,然后将其缩小线宽。
引用: 使用bezierPathWithRoundedRect 线宽20,框大小200 x 300,圆角半径50

paths

转换后如下:

viewSize 是路径的边界框
lineWidth 是线条的宽度
bezierPath 是您的 UIBezierPath

CGAffineTransform transform = CGAffineTransformMakeTranslation(lineWidth / 2.0,
                                                               lineWidth / 2.0);
transform = CGAffineTransformScale(transform, 
                                   (viewSize.width - lineWidth) / viewSize.width, 
                                   (viewSize.height - lineWidth) / viewSize.height);

CGPathRef reducedPath = CGPathCreateCopyByTransformingPath(bezierPath.CGPath, &transform);


更新

如果您想保持宽高比,缩放可以修改为在两个轴上都相等,使用两者中的最小因子。

CGFloat scale = viewSize.width < viewSize.height ? (viewSize.width - lineWidth) / viewSize.width :
                                                   (viewSize.height - lineWidth) / viewSize.height;

CGAffineTransform transform = CGAffineTransformMakeTranslation(lineWidth / 2.0, lineWidth / 2.0);
transform = CGAffineTransformScale(transform, scale, scale);

CGPathRef reducedPath = CGPathCreateCopyByTransformingPath(bezierPath.CGPath, &transform);

如果我的路径最初被某个未知角度旋转,这仍然有效吗?如果我应用比例,那么在这种情况下路径是否会发生错切? - Sudhanshu Monga
如果在执行此操作之前已经应用了旋转,它应该可以正常工作。至于剪切,我的解决方案不会保持长宽比,所以它可能会发生剪切。如果想要保持长宽比,缩放变换可以轻松地修改为在两个轴上等比缩放。只需在两个轴上同时执行两个缩放值中较小的那个即可。 - LGP
viewsize 是边界框,但如果我的路径是旋转的星形路径,并且我需要在内部添加边框,我该怎么做呢?因为这个解决方案适用于矩形。 - Sudhanshu Monga
我认为凸形状,如矩形、圆形等都没问题,但星形等凹形状会更或多或少地失真。问题在于,在星形边缘内部绘制边框会比在边缘上或外部绘制相对更尖锐的角度。话虽如此,当在相当大的形状上绘制细线时,失真可能甚至不可见。我没有一个正确的解决方案。 - LGP

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接