iOS UIBezierPath贝赛尔曲线详解

UIBezierPath是在画图,定制动画轨迹中都有应用。

UIBezierPath主要用来绘制矢量图形,它是基于Core Graphics对CGPathRef数据类型和path绘图属性的一个封装,所以是需要图形上下文的(CGContextRef),所以一般UIBezierPath在drawRect中使用。

本文主要介绍了iOS 贝塞尔曲线(UIBezierPath)属性、方法的相关详解资料,供大家参考,如有错漏,欢迎留言指正。

一、引入头文件:

#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
#import <UIKit/UIKitDefines.h>

1、Objective-C之Foundation框架

2、Core Graphics-Apple的矢量绘图框架

3、UIKitDefines-UIKit中的一些宏定义

二、如果需要每个属性或每个方法都去指定nonnull和nullable,是一件非常繁琐的事。苹果为了减轻我们的工作量,专门提供了两个宏:

NS_ASSUME_NONNULL_BEGIN
...
NS_ASSUME_NONNULL_END

宏定义:Nonnull区域设置(Audited Regions)

在这两个宏之间的代码,所有简单指针对象都被假定为nonnull,因此我们只需要去指定那些nullable的指针。

三、按位掩码(bitmask)

注意:并不是枚举

typedef NS_OPTIONS(NSUInteger, UIRectCorner) {
    UIRectCornerTopLeft     = 1 << 0,    // 指定UIView左上角为圆角
    UIRectCornerTopRight    = 1 << 1,    // 指定UIView右上角为圆角
    UIRectCornerBottomLeft  = 1 << 2,  // 指定UIView左下角为圆角
    UIRectCornerBottomRight = 1 << 3, // 指定UIView右下角为圆角
    UIRectCornerAllCorners  = ~0UL     // 指定UIView四个角均为圆角 
};

按位掩码(NS_OPTIONS)的语法和枚举(NS_ENUM)相同,但编译器会将它的值通过位掩码 | 组合在一起。

四、系统库头文件中的宏定义:

NS_CLASS_AVAILABLE_IOS(3_2) [@interface](https://my.oschina.net/u/996807) UIBezierPath : NSObject<NSCopying, NSCoding>

NS_CLASS_AVAILABLE_IOS(3_2) :代表只可以在iOS3.2及以后的版本中使用,如果在比3.2更老的版本中调用这个方法,就会引起崩溃

NS_DESIGNATED_INITIALIZER

NS_DESIGNATED_INITIALIZER :指定构造器,告诉调用者要用这个方法去初始化(构造)类对象。

正确使用NS_DESIGNATED_INITIALIZER

NS_RETURNS_INNER_POINTER

说明该方法返回的是一个对象的内部C指针

CF_RETURNS_NOT_RETAINED

标记为 CF_RETURNS_RETAINED 或 CF_RETURNS_NOT_RETAINED。编译器在编译时会自动为他们加上内存管理相关的调用。

五、方法属性详解:

// 创建UIBezierPath曲线对象
+ (instancetype)bezierPath;
// 创建画矩形的UIBezierPath曲线对象
+ (instancetype)bezierPathWithRect:(CGRect)rect;
// 创建根据矩形框的画内切圆的UIBezierPath曲线对象
+ (instancetype)bezierPathWithOvalInRect:(CGRect)rect;
// 创建画四个角都带圆角的矩形的UIBezierPath曲线对象
+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius; // rounds all corners with the same horizontal and vertical radius
// 创建可以针对四角中的某个角加圆角的UIBezierPath曲线对象
+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect byRoundingCorners:(UIRectCorner)corners cornerRadii:(CGSize)cornerRadii;
// 创建以某个中心点画弧线的UIBezierPath曲线对象
+ (instancetype)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;
// 根据已有路径创建UIBezierPath曲线对象
+ (instancetype)bezierPathWithCGPath:(CGPathRef)CGPath;

// 初始化方法
- (instancetype)init NS_DESIGNATED_INITIALIZER;
// 建议使用的初始化方法
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;

// Returns an immutable CGPathRef which is only valid until the UIBezierPath is further mutated.
// Setting the path will create an immutable copy of the provided CGPathRef, so any further mutations on a provided CGMutablePathRef will be ignored.
// 将UIBezierPath类转换成CGPath,类似于UIColor的CGColor
@property(nonatomic) CGPathRef CGPath;
// 转换成CGPath
- (CGPathRef)CGPath NS_RETURNS_INNER_POINTER CF_RETURNS_NOT_RETAINED;

// Path construction

// 移动到某一点
- (void)moveToPoint:(CGPoint)point;
// 向某一点绘制一条线
- (void)addLineToPoint:(CGPoint)point;
// 根据三个点绘制三次贝塞尔曲线
- (void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2;
// 根据两个点绘制二次贝塞尔曲线
- (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint;
// 根据圆心、半径画圆弧
- (void)addArcWithCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise NS_AVAILABLE_IOS(4_0);
// 闭合路径,即在终点与起点连一根线
- (void)closePath;

// 清空所有路径
- (void)removeAllPoints;

// Appending paths
// 追加路径
- (void)appendPath:(UIBezierPath *)bezierPath;

// Modified paths
// 扭转路径,即起点变成终点,终点变成起点
- (UIBezierPath *)bezierPathByReversingPath NS_AVAILABLE_IOS(6_0);

// Transforming paths
// 路径进行仿射变换
- (void)applyTransform:(CGAffineTransform)transform;

// Path info
// 只读类型,路径上是否有有效的元素
@property(readonly,getter=isEmpty) BOOL empty;
// 和view的bounds是不一样的,它获取path的X坐标、Y坐标、宽度,但是高度为0
@property(nonatomic,readonly) CGRect bounds;
// 当前path的位置,可以理解为path的终点
@property(nonatomic,readonly) CGPoint currentPoint;
// 是否路径中包含某个点
- (BOOL)containsPoint:(CGPoint)point;

// Drawing properties
// 路径线条的宽度
@property(nonatomic) CGFloat lineWidth;
/** path端点样式,有3种样式
* kCGLineCapButt:无端点
* kCGLineCapRound:圆形端点
* kCGLineCapSquare:方形端点(样式上和kCGLineCapButt是一样的,但是比kCGLineCapButt长一点)
*/
@property(nonatomic) CGLineCap lineCapStyle;
// 拐角样式
@property(nonatomic) CGLineJoin lineJoinStyle;
// 最大斜接长度(只有在使用kCGLineJoinMiter是才有效),边角的角度越小,斜接长度就会越大
@property(nonatomic) CGFloat miterLimit; // Used when lineJoinStyle is kCGLineJoinMiter
// 弯曲路径的渲染精度,默认为0.6,越小精度越高,相应的更加消耗性能
@property(nonatomic) CGFloat flatness;
// 单双数圈规则是否用于绘制路径,默认是NO
@property(nonatomic) BOOL usesEvenOddFillRule; // Default is NO. When YES, the even-odd fill rule is used for drawing, clipping, and hit testing.

// 绘制虚线
- (void)setLineDash:(nullable const CGFloat *)pattern count:(NSInteger)count phase:(CGFloat)phase;
// 获取虚线
- (void)getLineDash:(nullable CGFloat *)pattern count:(nullable NSInteger *)count phase:(nullable CGFloat *)phase;

// Path operations on the current graphics context
// 填充颜色
- (void)fill;
// 描边,路径创建需要描边才能显示出来
- (void)stroke;

// These methods do not affect the blend mode or alpha of the current graphics context
// 设置填充的混合模式
- (void)fillWithBlendMode:(CGBlendMode)blendMode alpha:(CGFloat)alpha;
// 设置描边的混合模式
- (void)strokeWithBlendMode:(CGBlendMode)blendMode alpha:(CGFloat)alpha;
// 利用当前的path进行裁剪,简单的说,就是一个path调用addClip之后,它所在的context的可见区域就变成了它的“fill area”,接下来的绘制,如果在这个区域外都会被无视。
- (void)addClip;

在生活中学习技术,在技术中感受生活。

——Jinfei Chen QQ:411282623

    原文作者:移动开发
    原文地址: https://my.oschina.net/chenjinfei/blog/887612
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞