iOS初级开发学习笔记:贝塞尔曲线的绘制学习

栏目: IOS · 发布时间: 6年前

内容简介:本文参考此文参考我们在项目中会接触到一些曲线的绘制,最初接触这个概念是因为有一个在屏幕右边的按钮,因为贴着屏幕,按钮右边是没有圆角的,而左上和左下是圆角,类似:还没知道贝塞尔曲线绘制之前,我是直接用

本文参考此文参考

我们在项目中会接触到一些曲线的绘制,最初接触这个概念是因为有一个在屏幕右边的按钮,因为贴着屏幕,按钮右边是没有圆角的,而左上和左下是圆角,类似:

iOS初级开发学习笔记:贝塞尔曲线的绘制学习

还没知道贝塞尔曲线绘制之前,我是直接用 _laborExplainButton.layer.cornerRadius = 33/2; 绘制一个四个角都是圆角的按钮,然后给出文字靠左属性 _laborExplainButton.titleLabel.textAlignment = NSTextAlignmentLeft; 设定按钮宽度时,多给出一段宽度,在用Masonary布局时让右边超出父视图,再慢慢调数值,让文字接近居中。

方法很笨,但是还算是实现了图片的效果(笑)。

但是往后出现的一些类似于tableView的紧密相连的cell的第一个cell左上和右上为圆角的需求,总不能再这样“投机”了,就开始学习到了用贝塞尔曲线实现。

本笔记将从苹果官方API:UIBezierPath.h文件的各种方法解释、介绍出发,介绍常用的一些方法和流程,再对具体案例做实现介绍,做一个从学到用的总结,不能做到所有方法方面都顾及,更深的更复杂的绘制实现还待后续学习补充。

一、UIBezierPath的概念

UIBezierPath是在iOS开发中绘制矢量图或者路径的时候会经常使用的一个部分,在UIKit里面是CoreGraphics对path的封装,使用UIBezierPath可以绘制直线、矩形、椭圆、不规则图形、多边形和贝塞尔曲线等,只要是能想到的线条都能画出来。

二、UIBezierPath.h内方法介绍

// 用来对某(几)个角进行贝塞尔绘制
typedef NS_OPTIONS(NSUInteger, UIRectCorner) {
    UIRectCornerTopLeft     = 1 << 0,
    UIRectCornerTopRight    = 1 << 1,
    UIRectCornerBottomLeft  = 1 << 2,
    UIRectCornerBottomRight = 1 << 3,
    UIRectCornerAllCorners  = ~0UL
};


// 初始化无形装的贝塞尔曲线
+ (instancetype)bezierPath;
// 初始化矩形贝塞尔曲线
+ (instancetype)bezierPathWithRect:(CGRect)rect;
// 绘制椭圆(圆形)贝塞尔曲线
+ (instancetype)bezierPathWithOvalInRect:(CGRect)rect;
// 绘制含有圆角的贝塞尔曲线
+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius; // rounds all corners with the same horizontal and vertical radius
// 绘制可选择圆角方位的贝塞尔曲线
+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect byRoundingCorners:(UIRectCorner)corners cornerRadii:(CGSize)cornerRadii;
// 绘制圆弧曲线
+ (instancetype)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;
// 根据CGPathRef绘制贝塞尔曲线
+ (instancetype)bezierPathWithCGPath:(CGPathRef)CGPath;

- (instancetype)init NS_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;


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

// 路径拼接
- (void)appendPath:(UIBezierPath *)bezierPath;

// 返回一个与当前路径相反的新的贝塞尔路径对象
- (UIBezierPath *)bezierPathByReversingPath NS_AVAILABLE_IOS(6_0);

// 路径进行仿射变换
- (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;
// 路径是否包含点point
- (BOOL)containsPoint:(CGPoint)point;

// Drawing properties

// 边框高度
@property(nonatomic) CGFloat lineWidth;
// 端点类型
@property(nonatomic) CGLineCap lineCapStyle;
// 线条连接类型
@property(nonatomic) CGLineJoin lineJoinStyle;
// 线条最大宽度最大限制
@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;

// 修改当前图形上下文的绘图区域可见,随后的绘图操作导致呈现内容只有发生在指定路径的填充区域
- (void)addClip;

复制代码

三、UIBezierPath的使用

UIBezierPath是对CGPathRef的封装,它提供了CGPath属性使我们在开发过程中获取底层的path,在创建矢量图形的时候,把图形拆解成一条或者多条线段,然后拼接在一起,每条线段的终点都是下一条线段的起点,这就是大概的实现思路。具体步骤如下:

1、创建一个UIBezierPath对象;

2、用moveToPoint:方法设置初始线段的起点;

3、添加线段,定义一个或者多个子路径;

4、修改UIBezierPathUIBezierPath的绘图部分的相关属性;

一个cell顶部两角切圆角的简单实现:

效果图:

iOS初级开发学习笔记:贝塞尔曲线的绘制学习

图片是个UIImageView,起初对背景的白色view切了四个角的圆角,发现这个UIImageView还是四角尖尖,再对UIImageView切圆角,变成了四角圆圆....所以,在对背景view切好四个角圆角后,我们还要用贝塞尔,切UIImageView的上两个角圆角:

但是,我用的是Masonary布局,在懒加载中写贝塞尔相关属性,并不能实现,因为一开始不能得到UIImageView的布局,所以研究了一番,我们在 - (void)layoutSubviews; 方法中才去写切圆角操作,这个方法是在布局完之后会走一次的,很好的解决了取不到范围的问题。

具体:

- (void)layoutSubviews{
    [super layoutSubviews];
    //  切上上两角圆角
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.coverImageView.bounds byRoundingCorners: UIRectCornerTopLeft|UIRectCornerTopRight cornerRadii:CGSizeMake(5, 5)];
    CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
    // frame为UIImageView的bounds
    maskLayer.frame = self.coverImageView.bounds;
    maskLayer.path = maskPath.CGPath;
    self.coverImageView.layer.mask = maskLayer;
}
复制代码

项目中其他类似的情况都触类旁通,使用此方法解决。

这里其实是UIBezierPath结合其他layer使用。 原则上使用UIBezierPath主要只是画出形状或画出一个图形的路径path,但是它也可以配合其他的layer使用(CAShapeLayer,CAGradientLayer等),layer可以添加动画,所以UIBezierPath结合layer使用效果会更棒。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Numerical Linear Algebra

Numerical Linear Algebra

Lloyd N. Trefethen、David Bau III / SIAM: Society for Industrial and Applied Mathematics / 1997-06-01 / USD 61.00

Numerical Linear Algebra is a concise, insightful, and elegant introduction to the field of numerical linear algebra.一起来看看 《Numerical Linear Algebra》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具