要在特定的内绘制实心圆弧CGSize
,可以这样定义UIBezierPath
:
- (UIBezierPath * _Nullable)pathOfArcWithinSize:(CGSize)size {
if (size.width == 0 || size.height <= 0) return nil;
CGFloat theta = M_PI - atan2(size.width / 2.0, size.height) * 2.0;
CGFloat radius = self.bounds.size.height / (1.0 - cos(theta));
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(0, 0)];
[path addArcWithCenter:CGPointMake(size.width / 2.0, -radius + size.height) radius:radius startAngle:M_PI_2 + theta endAngle:M_PI_2 - theta clockwise:false];
[path closePath];
return path;
}
在给定视图的高度和宽度的情况下,这只是使用一些三角函数来计算圆弧的角度和半径。
有了该CAShapeLayer
路径后,您可以使用该路径构造一个,然后将该路径添加为a的子层,UIView
也可以实现自己的在该路径drawRect
上调用的方法fill
。(或者,考虑到您已经用core-graphics标记了它,也可以drawRect
使用CoreGraphics调用进行自定义,但是我不确定为什么要这么做。)
例如,您可以定义一个CurvedView
使用CAShapeLayer
以下内容的类:
// CurvedView.h
#import <UIKit/UIKit.h>
IB_DESIGNABLE
@interface CurvedView : UIView
@property (nonatomic, strong) IBInspectable UIColor *fillColor;
@end
和
// CurvedView.m
#import "CurvedView.h"
@interface CurvedView ()
@property (nonatomic, weak) CAShapeLayer *curvedLayer;
@end
@implementation CurvedView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self configureView];
}
return self;
}
- (instancetype _Nullable)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
if (self) {
[self configureView];
}
return self;
}
- (void)configureView {
self.fillColor = [UIColor whiteColor];
CAShapeLayer *layer = [CAShapeLayer layer];
layer.fillColor = self.fillColor.CGColor;
layer.strokeColor = [UIColor clearColor].CGColor;
layer.lineWidth = 0;
[self.layer addSublayer:layer];
self.curvedLayer = layer;
}
- (void)setFillColor:(UIColor *)fillColor {
_fillColor = fillColor;
self.curvedLayer.fillColor = fillColor.CGColor;
}
- (void)layoutSubviews {
[super layoutSubviews];
self.curvedLayer.path = [self pathOfArcWithinSize:self.bounds.size].CGPath;
}
- (UIBezierPath * _Nullable)pathOfArcWithinSize:(CGSize)size {
if (size.width == 0 || size.height <= 0) return nil;
CGFloat theta = M_PI - atan2(size.width / 2.0, size.height) * 2.0;
CGFloat radius = self.bounds.size.height / (1.0 - cos(theta));
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(0, 0)];
[path addArcWithCenter:CGPointMake(size.width / 2.0, -radius + size.height) radius:radius startAngle:M_PI_2 + theta endAngle:M_PI_2 - theta clockwise:false];
[path closePath];
return path;
}
@end
产生:
或者,如果您更愿意使用该drawRect
方法而不是使用CAShapeLayer
:
// CurvedView.m
#import "CurvedView.h"
@implementation CurvedView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self configureView];
}
return self;
}
- (instancetype _Nullable)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
if (self) {
[self configureView];
}
return self;
}
- (void)configureView {
self.fillColor = [UIColor whiteColor];
}
- (void)setFillColor:(UIColor *)fillColor {
_fillColor = fillColor;
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect {
UIBezierPath *path = [self pathOfArcWithinSize:self.bounds.size];
[self.fillColor setFill];
[path fill];
}
- (UIBezierPath * _Nullable)pathOfArcWithinSize:(CGSize)size {
if (size.width == 0 || size.height <= 0) return nil;
CGFloat theta = M_PI - atan2(size.width / 2.0, size.height) * 2.0;
CGFloat radius = self.bounds.size.height / (1.0 - cos(theta));
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(0, 0)];
[path addArcWithCenter:CGPointMake(size.width / 2.0, -radius + size.height) radius:radius startAngle:M_PI_2 + theta endAngle:M_PI_2 - theta clockwise:false];
[path closePath];
return path;
}
@end
如果希望弧形占据视图的底部,则路径应如下所示:
- (UIBezierPath * _Nullable)pathOfArcWithinSize:(CGSize)size {
if (size.width == 0 || size.height <= 0) return nil;
CGFloat theta = M_PI - atan2(size.width / 2.0, size.height) * 2.0;
CGFloat radius = self.bounds.size.height / (1.0 - cos(theta));
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(0, size.height)];
[path addArcWithCenter:CGPointMake(size.width / 2.0, radius) radius:radius startAngle:M_PI_2 * 3.0 + theta endAngle:M_PI_2 * 3.0 - theta clockwise:false];
[path closePath];
return path;
}
本质上,这与theta
和相同radius
,但从左下角开始,将设置center
为size.width / 2.0, radius
,并从M_PI_2 * 3.0
±弧起theta
:
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句