iOS动画 —— UIBezierPath

计算机软件开发 2024-10-2 22:29:29 91 0 来自 中国
简介

UIBezierPath类创建基于矢量的路径,例如椭圆大概矩形,大概有多个直线和曲线段构成的外形。
UIBezierPath是UIKit中的一个关于图形绘制的类,是通过Quartz 2D也就是CG(Core Graphics)CGPathRef的封装得到的,从高级特性支持来看不及CG。
利用UIBezierPath,你只能在当前图形上下文中绘制。 CGContextRef即图形上下文。
1.重写UIView的drawRect方法,在该方法里便可得到context;
2.调用UIGraphicsBeginImageContextWithOptions方法得到
drawRect: 触发触发机遇
1、当view第一次表现到屏幕上时;
2、当调用view的setNeedsDisplay大概setNeedsDisplayInRect:方法时。
绘制流程


  • 初始化一个 UIBezierPath 对象
  • 设置相关的属性;
  • 调用 -moveToPoint: 方法初始线段的出发点;
  • 添加线段大概曲线段去构建一个大概多个子路径;
- (void)drawRectCGRect)rect // 重写drawRect方法{    // 1.初始化图形相应的UIBezierPath对象    UIBezierPath* aPath = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 200, 200)]; // 2.    // 2.设置一些修饰属性     aPath.lineWidth = 8.0;    //路径的尽头外形,    aPath.lineCapStyle = kCGLineCapRound;     //路径的毗连点外形    aPath.lineJoinStyle = kCGLineCapRound;     UIColor *color = [UIColor colorWithRed:0 green:0 blue:0.7 alpha:1];    [color set];     // 3.出发点    [aPath moveToPoint:CGPointMake(20, 20)];    // 4.绘制线条    [aPath addLineToPoint:CGPointMake(100, 100)];    [aPath stroke]; // 渲染,完成绘制}创建 UIBezierPath


  • 创建而且返回一个新的 UIBezierPath 对象
+ (instancetype) bezierPath;

  • 通过一个矩形, 创建而且返回一个新的 UIBezierPath 对象
/**  * 该方法将会创建一个闭合路径, 起始点是 rect 参数的的 origin, 而且按照顺时针方向添加直线, 终极形成矩形  * @param rect:   矩形路径的 Frame  */+ (instancetype)bezierPathWithRectCGRect)rect;

  • 通过一个指定的矩形中的椭圆形, 创建而且返回一个新的 UIBezierPath 对象
/**  * 该方法将会创建一个闭合路径,  该方法会通过顺时针的绘制贝塞尔曲线, 绘制出一个近似椭圆的外形. 如果 rect 参数指定了一个矩形, 那么该 UIBezierPath 对象将会形貌一个圆形.  * @param rect:   矩形路径的 Frame  */+ (instancetype)bezierPathWithOvalInRectCGRect)rect;

  • 根据一个圆角矩形, 创建而且返回一个新的 UIBezierPath 对象
/**  * 该方法将会创建一个闭合路径,  该方法会顺时针方向一连绘制直线和曲线.  当 rect 为正方形时且 cornerRadius 便是边长一半时, 则该方法会形貌一个圆形路径.  * @param rect:   矩形路径的 Frame  * @param cornerRadius:   矩形的圆角半径  */+ (instancetype) bezierPathWithRoundedRectCGRect)rect                               cornerRadiusCGFloat)cornerRadius;

  • 根据一个圆角矩形, 创建而且返回一个新的 UIBezierPath 对象
/**  * 该方法将会创建一个闭合路径,  该方法会顺时针方向一连绘制直线和曲线.    * @param rect:   矩形路径的 Frame  * @param corners:   UIRectCorner 枚举范例, 指定矩形的哪个角变为圆角  * @param cornerRadii:   矩形的圆角半径  */+ (instancetype) bezierPathWithRoundedRectCGRect)rect                          byRoundingCornersUIRectCorner)corners                               cornerRadiiCGSize)cornerRadii;

  • 通过一个圆弧, 创建而且返回一个新的 UIBezierPath 对象
/**  * 该方法会创建出一个开放路径, 创建出来的圆弧是圆的一部门. 在默认的坐标体系中, 开始角度 和 竣事角度 都是基于单元圆的(看下面这张图). 调用这个方法之后, currentPoint 将会设置为圆弧的竣事点.  * 举例来说: 指定实在角度为0, 指定竣事角度为π, 设置 clockwise 属性为 YES, 将会绘制出圆的下半部门.  * 然而当我们不修改起始角度 和 竣事角度, 我们仅仅将 clockwise 角度设置为 NO, 则会绘制出来一个圆的上半部门.  * @param center:   圆心  * @param radius: 半径  * @param startAngle:   起始角度  * @param endAngle:   竣事角度  * @param clockwise:   是否顺时针绘制  */+ (instancetype) bezierPathWithArcCenterCGPoint)center                                   radiusCGFloat)radius                               startAngle:(CGFloat)startAngle                                 endAngle:(CGFloat)endAngle                                clockwise:(BOOL)clockwise; 1.jpeg

  • 通过一个 CGPath, 创建而且返回一个新的 UIBezierPath 对象
+ (instancetype) bezierPathWithCGPath:(CGPathRef)CGPath;

  • 创建并返回一个新的BezierPath, 这个 BezierPath 的方向是原 BezierPath 的反方向
/**  * 通过该方法反转一条路径, 并不会修改该路径的样子. 它仅仅是修改了绘制的方向  * @return: 返回一个新的 UIBezierPath 对象, 外形和原来路径的外形一样,  *          但是绘制的方向相反.  */- (UIBezierPath *) bezierPathByReversingPath;构造路径


  • 将 UIBezierPath 对象的 currentPoint 移动到指定的点
/**  * 如果当前有正在绘制的子路径, 该方法则会隐式的竣事当前路径,   * 并将 currentPoint 设置为指定点. 当上一条子路径被克制, 该方法  * 实际上并不会去闭合上一条子路径. 以是上一条自路径的起始点 和  * 竣事点并没有被链接.  * 对于大多数构造路径相关的方法而言, 在你绘制直线或曲线之前, 须要先调用这个方法.  * @param point:   当前坐标体系中的某一点  */- (void)moveToPoint:(CGPoint)point;

  • 在当前子路径中追加一条直线
/**  * 该方法将会从 currentPoint 到 指定点 链接一条直线.   * Note: 在追加完这条直线后, 该方法将会更新 currentPoint 为 指定点  *       调用该方法之前, 你必须先设置 currentPoint. 如果当前绘制路径  *       为空, 而且未设置 currentPoint, 那么调用该方法将不会产生任何  *       结果.  * @param point:   绘制直线的尽头坐标, 当前坐标体系中的某一点  */- (void)addLineToPoint:(CGPoint)point;

  • 在当前子路径中追加一条圆弧
/**  * 该方法将会从 currentPoint 添加一条指定的圆弧.  * 该方法的先容和构造方法中的一样. 请前去上文检察  * @param center: 圆心  * @param radius: 半径  * @param startAngle: 起始角度  * @param endAngle: 竣事角度  * @param clockwise: 是否顺时针绘制  */- (void)addArcWithCenter:(CGPoint)center                   radius:(CGFloat)radius               startAngle:(CGFloat)startAngle                 endAngle:(CGFloat)endAngle                clockwise:(BOOL)clockwise NS_AVAILABLE_IOS(4_0);

  • 在当前 子路经中追加一条 二次贝塞尔曲线
/**  * 该方法将会从 currentPoint 到 指定的 endPoint 追加一条二次贝塞尔曲线.  * currentPoint、endPoint、controlPoint 三者的关系终极界说了二次贝塞尔曲线的外形.  * 二次贝塞尔曲线的弯曲由一个控制点来控制. 如下图所示  * Note: 调用该方法前, 你必须先设置 currentPoint, 如果路径为空,   *       而且尚未设置 currentPoint, 调用该方法则不会产生任何结果.   *       当添加完贝塞尔曲线后, 该方法将会自动更新 currentPoint 为  *       指定的竣事点  * @param endPoint: 尽头  * @param controlPoint: 控制点  */- (void)addQuadCurveToPoint:(CGPoint)endPoint                controlPoint:(CGPoint)controlPoint; 2.gif

  • 在当前 子路经中追加一条 三次贝塞尔曲线
/**  * 该方法将会从 currentPoint 到 指定的 endPoint 追加一条三次贝塞尔曲线.  * 三次贝塞尔曲线的弯曲由两个控制点来控制. 如下图所示  * Note: 调用该方法前, 你必须先设置 currentPoint, 如果路径为空,   *       而且尚未设置 currentPoint, 调用该方法则不会产生任何结果.   *       当添加完贝塞尔曲线后, 该方法将会自动更新 currentPoint 为  *       指定的竣事点  * @param endPoint: 尽头  * @param controlPoint1: 控制点1  * @param controlPoint2: 控制点2  */- (void)addCurveToPoint:(CGPoint)endPoint           controlPoint1:(CGPoint)controlPoint1           controlPoint2:(CGPoint)controlPoint2;

  • 关闭当前子路经
/**  * 该方法将会从 currentPoint 到子路经的出发点 绘制一条直线,   * 以此来关闭当前的自路径. 紧接着该方法将会更新 currentPoint  * 为 刚添加的这条直线的尽头, 也就是当前子路经的出发点.  */- (void)closePath;

  • 删除 UIBezierPath 对象中的全部点, 结果也就等同于删除了全部子路经
- (void)removeAllPoints;

  • 将指定 UIBezierPath 中的内容添加到当前 UIBezierPath 对象中
/**  * 该方法将会在当前 UIBezierPath 对象的路径中追加  * 指定的 UIBezierPath 对象中的内容.   */- (void)appendPath:(UIBezierPath *)bezierPath;

  • UIBezierPath 中的 CGPath 对象
/**  * 获取这个属性, 你将会得到一个不可变的 CGPathRef 对象,  * 他可以传入 CoreGraphics 提供的函数中  * 你可以是用 CoreGraphics 框架提供的方法创建一个路径,   * 并给这个属性赋值, 当时设置了一个新的路径后,   * 这个将会对你给出的路径对象举行 Copy 操纵  */@property(nonatomic) CGPathRef CGPath;

  • 绘图路径中的当前点
/**  * 该属性的值, 将会是下一条绘制的直线或曲线的起始点.  * 如果当前路径为空, 那么该属性的值将会是 CGPointZero  */@property(nonatomic, readonly) CGPoint currentPoint;绘图属性


  • 线宽
/**  * 线宽属性界说了 `UIBezierPath` 对象中绘制的曲线规格. 默以为: 1.0  */@property(nonatomic) CGFloat lineWidth;

  • 曲线尽头样式
/**  * 该属性应用于曲线的尽头和出发点. 该属性在一个闭合子路经中是无结果的. 默以为: kCGLineCapButt  */@property(nonatomic) CGLineCap lineCapStyle;// CGPath.h/* Line cap styles. */typedef CF_ENUM(int32_t, CGLineCap) {    kCGLineCapButt,    kCGLineCapRound,    kCGLineCapSquare}; 4.png

  • 曲线毗连点样式
/**  * 默以为: kCGLineJoinMiter.  */@property(nonatomic) CGLineJoin lineJoinStyle;// CGPath.h/* Line join styles. */typedef CF_ENUM(int32_t, CGLineJoin) {    kCGLineJoinMiter,    kCGLineJoinRound,    kCGLineJoinBevel};

  • 内角和外角间隔
/**  * 两条线交汇处内角和外角之间的最大间隔, 只有当毗连点样式为 kCGLineJoinMiter  * 时才访问效,最大限定为10  * 我们都知道, 两条直线相交时, 夹角越小, 斜接长度就越大.  * 该属性就是用来控制最大斜接长度的.  * 当我们设置了该属性, 如果斜接长度高出我们设置的范围,   * 则毗连处将会以 kCGLineJoinBevel 毗连范例举行表现.  */@property(nonatomic) CGFloat miterLimit; 7.png

  • 渲染精度
/**  * 该属性用来确定渲染曲线路径的准确度.  * 该属性的值用来丈量真实曲线的点和渲染曲线的点的最大答应间隔.  * 值越小, 渲染精度越高, 会产生相对更平滑的曲线, 但是须要泯灭更  * 多的盘算时间. 值越大导致则会低沉渲染精度, 这会使得渲染的更迅  * 速. flatness 的默认值为 0.6.  * Note: 大多数情况下, 我们都不须要修改这个属性的值. 然而当我们  *       渴望以最小的斲丧去绘制一个临时的曲线时, 我们大概会临时增  *       大这个值, 来得到更快的渲染速率.  */@property(nonatomic) CGFloat flatness;

  • 是否利用基偶添补规则 -- 详细先容
/**  * 设置为 YES, 则路径将会利用 基偶规则 (even-odd) 举行添补.  * 设置为 NO,  则路径将会利用 非零规则 (non-zero) 规则举行添补.  */@property(nonatomic) BOOL usesEvenOddFillRule;

  • 虚线
/**  * @param pattern: 该属性是一个 C 语言的数组, 此中每一个元素都是 CGFloat  *                 数组中的元素代表着线段每一部门的长度, 第一个元素代表线段的第一条线,  *                 第二个元素代表线段中的第一个间隙. 这个数组中的值是轮番的. 来表明一下  *                 什么叫轮番的.   *                 举个例子: 声明一个数组 CGFloat dash[] = @{3.0, 1.0};   *                 这意味着绘制的虚线的第一部门长度为3.0, 第一个间隙长度为1.0, 虚线的  *                 第二部门长度为3.0, 第二个间隙长度为1.0\. 以此类推.  * @param count: 这个参数是 pattern 数组的个数  * @param phase: 这个参数代表着, 虚线从哪里开始绘制.  *                 举个例子: 这是 phase 为 6\. pattern[] = @{5, 2, 3, 2}; 那么虚线将会  *                 第一个间隙的中央部门开始绘制, 如果不是很明确就请继续往下看,  *                 下文实战部门会对虚线举行解说.  */- (void)setLineDash:(const CGFloat *)pattern              count:(NSInteger)count              phase:(CGFloat)phase;

  • 重新获取虚线的模式
/**  * 该方法可以重新获取之前设置过的虚线样式.  *  Note:  pattern 这个参数的容量必须大于该方法返回数组的容量.  *         如果无法确定命组的容量, 那么可以调用两次该方法, 第一次  *         调用该方法的时间, 传入 count 参数, 然后在用 count 参数  *         来申请 pattern 数组的内存空间. 然后再第二次正常的调用该方法  */- (void)getLineDash:(CGFloat *)pattern               count:(NSInteger *)count              phase:(CGFloat *)phase;绘制路径


  • 添补路径
/**  * 该方法当前的添补颜色 和 绘图属性对路径的封闭地区举行添补.  * 如果当前路径是一条开放路径, 该方法将会隐式的将路径举行关闭后举行添补  * 该方法在举行添补操纵之前, 会自动生存当前绘图的状态, 以是我们不须要  * 本技艺动的去生存绘图状态了.   */- (void)fill;

  • 利用肴杂模式举行添补
/**  * 该方法当前的添补颜色 和 绘图属性 (外加指定的肴杂模式 和 透明度)   * 对路径的封闭地区举行添补. 如果当前路径是一条开放路径, 该方法将  * 会隐式的将路径举行关闭后举行添补  * 该方法在举行添补操纵之前, 会自动生存当前绘图的状态, 以是我们不须要  * 本技艺动的去生存绘图状态了.   *  * @param blendMode: 肴杂模式决定了怎样和已经存在的被渲染过的内容举行合成  * @param alpha: 添补路径时的透明度  */- (void)fillWithBlendMode:(CGBlendMode)blendMode                     alpha:(CGFloat)alpha;

  • 绘制路径
- (void)stroke;

  • 利用肴杂模式举行添补
/**  * @param blendMode: 肴杂模式决定了怎样和已经存在的被渲染过的内容举行合成  * @param alpha: 添补路径时的透明度  */- (void)strokeWithBlendMode:(CGBlendMode)blendMode                      alpha:(CGFloat)alpha;剪切路径


  • 剪切路径
/**  *  该方法将会修改当前绘图上下文的可视地区.  *  当调用这个方法之后, 会导致接下来全部的渲染  *  操纵, 只会在剪切下来的地区内举行, 地区外的  *  内容将不会被渲染.  *  如果你渴望实行接下来的绘图时, 删除剪切地区,  *  那么你必须在调用该方法前, 先利用 CGContextSaveGState 方法  *  生存当前的绘图状态, 当你不再须要这个剪切地区  *  的时间, 你只须要利用 CGContextRestoreGState 方法  *  来规复之前生存的绘图状态就可以了.  * @param blendMode: 肴杂模式决定了怎样和  *                   已经存在的被渲染过的内容举行合成  * @param alpha: 添补路径时的透明度  */- (void)addClip;Hit Detection


  • 是否包罗某个点
/**  *  该方法返回一个布尔值, 当曲线的覆盖地区包罗  * 指定的点(内部点), 则返回 YES, 否则返回 NO.   * Note: 如果当前的路径是一个开放的路径, 那么  *       就算指定点在路径覆盖范围内, 该方法仍旧会  *       返回 NO, 以是如果你想判定一个点是否在一个  *       开放路径的范围内时, 你须要先Copy一份路径,  *       并调用 -(void)closePath; 将路径封闭, 然后  *       再调用此方法来判定指定点是否是内部点.  * @param point: 指定点.  */- (BOOL) containsPoint:(CGPoint)point;

  • 路径是否为空
/**  * 检测当前路径是否绘制过直线或曲线.  * Note: 记着, 就算你仅仅调用了 moveToPoint 方法  *       那么当前路径也被看做不为空.  */@property (readonly, getter=isEmpty) BOOL empty;

  • 路径覆盖的矩形地区
/**  * 该属性形貌的是一个可以或许完全包罗路径中全部点  *  的一个最小的矩形地区. 该地区包罗二次贝塞尔  *  曲线和三次贝塞尔曲线的控制点.  */@property (nonatomic, readonly) CGRect bounds;Apply Transform

/**  * 该方法将会直接对路径中的全部点举行指定的放射  * 变更操纵.   */- (void)applyTransform:(CGAffineTransform)transform;实例

8.png Demo: https://github.com/iOSlixiang/Animations.git
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-10-18 16:45, Processed in 0.169955 second(s), 35 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表