【问题标题】:How to Draw a Bezier Curve in UIView如何在 UIView 中绘制贝塞尔曲线
【发布时间】:2016-06-14 07:08:07
【问题描述】:

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

我也想知道如何从水平轴翻转曲线,这样我的弧在顶部,底部在底部。

【问题讨论】:

  • 我觉得这个链接对你有用stackoverflow.com/questions/12904767/…
  • 他们对使用 Image as curve 有任何限制吗? @Diksha
  • @RahulMishra 我必须使用 UIView 而不是图像
  • @Diksha 您可以使用UIView 并在其中放置UIImageView ..并放置具有曲线的图像。我做了同样的功能

标签: ios objective-c core-graphics uibezierpath


【解决方案1】:

要在特定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,然后将其添加为UIView 的子层,或者你可以实现自己的drawRect 方法,在该路径上调用fill。 (或者,鉴于您已使用 标记此内容,您也可以使用 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

产生:

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

本质上,thetaradius 是一样的,但是从左下角开始,将center 设置为size.width / 2.0, radius,并从M_PI_2 * 3.0 ± theta 开始:

【讨论】:

  • 谢谢rob..你又救了我..我想学这个..实际上不知道如何处理UIBeizers,我想学这个,所以你能帮我从哪里开始...谢谢...:)
  • @Elan - 有关贝塞尔路径的基础知识,请参阅 Apple 文档 (developer.apple.com/library/ios/documentation/2DDrawing/…) 或谷歌“uibezierpath 教程”。为了使数学达到理想的路径,这是从时间的迷雾中借鉴我的旧高中三角学。 :) 最重要的是,只需开始在自定义UIView 子类(如上)或CAShapeLayer 中构建自己的UIBezierPath,我相信你会很快学会的。它并不像看起来那么难。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-26
  • 2013-08-21
  • 1970-01-01
  • 2012-04-21
  • 1970-01-01
  • 2014-09-29
相关资源
最近更新 更多