如何使用quartz2d/coregraphics绘制圆角三角形

Posted

技术标签:

【中文标题】如何使用quartz2d/coregraphics绘制圆角三角形【英文标题】:How to draw a triangle with rounded corners using quartz2d/coregraphics 【发布时间】:2012-11-24 04:27:01 【问题描述】:

好吧,所以我想像这样画一个三角形:

目前我正在使用 CAShapeLayer 的组合并使用 UIBezierPath 创建路径(代码如下),然后将其用作另一层的掩码(self.layer,因为我在 UIView 子类中,而不是而不是设置 layerclass 我这样做是为了保留初始层)

反正代码:

_bezierPath = [[UIBezierPath bezierPath] retain];
#define COS30 0.86602540378
#define SIN30 0.5
[_bezierPath moveToPoint:(CGPoint)self.frame.size.width/2.f-r*SIN30,r*COS30];
[_bezierPath addArcWithCenter:(CGPoint)self.frame.size.width/2.f,r*COS30*2.f radius:r startAngle:2*M_PI/3.f endAngle:M_PI/3.f clockwise:YES];
[_bezierPath addLineToPoint:(CGPoint)self.frame.size.width-r*SIN30,self.frame.size.height-r*COS30];
[_bezierPath addArcWithCenter:(CGPoint)self.frame.size.width-r*SIN30-r,self.frame.size.height-r*COS30 radius:r startAngle:0.f endAngle:-M_PI/3.f clockwise:YES];
[_bezierPath addLineToPoint:(CGPoint)r*SIN30,self.frame.size.height-r*COS30];
[_bezierPath addArcWithCenter:(CGPoint)r*SIN30+r,self.frame.size.height-r*COS30 radius:r startAngle:4*M_PI/3.f endAngle:M_PI clockwise:YES];
[_bezierPath closePath];
CAShapeLayer *s = [CAShapeLayer layer];
s.frame = self.bounds;
s.path = _bezierPath.CGPath;
self.layer.mask = s;
self.layer.backgroundColor = [SLInsetButton backgroundColorForVariant:SLInsetButtonColorForSLGamePieceColor(_color)].CGColor;

不幸的是结果不是我想要的,而是角落变成了小旋钮(好像它转动太多了)

提前致谢

【问题讨论】:

为什么是 cos (30) 而不是 60? 你指的是哪种情况? 【参考方案1】:

一位才华横溢的朋友(John Heaton,如果你遇到他,他非常棒)让我想起了核心图形部署的 lineCap 和 lineJoin 属性。

某处:

#define border (10.f)

在你的界面中:

@property (nonatomic, strong) UIBezierPath *bezierPath;

在你的初始化中,创建一个像这样的短路径:

CGFloat inset = border / 2.f;
UIBezierPath *bezierPath = [UIBezierPath bezierPath];
[bezierPath moveToPoint:(CGPoint) self.frame.size.width/2.f, inset ];
[bezierPath addLineToPoint:(CGPoint) self.frame.size.width - inset, self.frame.size.height - inset ];
[bezierPath addLineToPoint:(CGPoint) a, self.frame.size.height - a ];
[bezierPath closePath];

self.bezierPath = bezierPath;

然后在您的 drawRect: 方法中执行以下操作:

CGContextRef c = UIGraphicsGetCurrentContext(), context = c;
CGColorRef col = [UIColor redColor].CGColor;
CGColorRef bcol = [UIColor redColor].CGColor;
CGContextSetFillColorWithColor(c, col);
CGContextSetStrokeColorWithColor(c, bcol);
CGContextSetLineWidth(c, border);
CGContextSetLineJoin(c, kCGLineJoinRound);
CGContextSetLineCap(c, kCGLineCapRound);
CGContextAddPath(c, self.bezierPath.CGPath);
CGContextStrokePath(c);
CGContextAddPath(c, self.bezierPath.CGPath);
CGContextFillPath(c);

这将正确地为您提供三角形上的圆角,还可以选择具有边框或轮廓

【讨论】:

考虑用const替换#define 我选择使用宏而不是像static const 这样的宏,因为你不需要用指针来引用数字,这里不需要额外的类型检查(它在一个假设它是一个浮点数的例程)并且它打开了在编译时使用cli args或在xcode的配置中提供这个常量的能力(ofc名称border不是最好的,应该改变,但这段代码应该'不是简单的复制/粘贴,应该通读和思考)。 我明白了,但是如果宏改了是不是整个项目都重新编译了? 老实说,我不确定它是重新编译整个项目还是只重新编译必要的文件 - 确保只重新编译该文件的一种方法是仅更改该文件上的标志。无论如何,从我的角度来看,它是一个或六个另一个中的 6 个 - 在我使用它的情况下,使用宏似乎没有好处或坏处,而不是 static const

以上是关于如何使用quartz2d/coregraphics绘制圆角三角形的主要内容,如果未能解决你的问题,请参考以下文章

[精选] Mysql分表与分库如何拆分,如何设计,如何使用

如果加入条件,我该如何解决。如果使用字符串连接,我如何使用

如何使用本机反应创建登录以及如何验证会话

如何在自动布局中使用约束标识符以及如何使用标识符更改约束? [迅速]

如何使用 AngularJS 的 ng-model 创建一个数组以及如何使用 jquery 提交?

如何使用laravel保存所有行数据每个行名或相等