gpt4 book ai didi

ios - 如何在UIView中绘制贝塞尔曲线

转载 作者:可可西里 更新时间:2023-11-01 06:24:08 24 4
gpt4 key购买 nike

我需要在 UIView 中制作一条曲线,如下图所示。我必须使用 UIBezierPath。请帮我解决这个问题。

我还想知道如何从水平轴翻转曲线,以便在顶部有圆弧,在底部有底部。

Example of bezier path

最佳答案

要在特定的 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;
}

这只是使用一点三角函数来计算给定 View 高度和宽度的弧的角度和半径。

一旦有了它,您就可以使用该路径构造一个 CAShapeLayer,然后将其添加为 UIView 的子层,或者您可以实现自己的 在该路径上调用 fill 的 drawRect 方法。 (或者,假设您已使用 对其进行标记,您也可以使用 CoreGraphics 调用执行自定义 drawRect,但我不确定您为什么要这样做。)

例如,您可以定义一个使用 CAShapeLayerCurvedView 类:

//  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

产生:

enter image description here

或者,如果您更愿意使用 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

如果你想让圆弧占据 View 的底部,路径应该是这样的:

- (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;
}

本质上,这与 thetaradius 相同,但从左下角开始,将 center 设置为 size。 M_PI_2 * 3.0 ± theta 的宽度/2.0、半径 和弧度:

enter image description here

关于ios - 如何在UIView中绘制贝塞尔曲线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37805197/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com