关于贝塞尔曲线

本文深入讲解了iOS开发中使用UIBezierPath和CAShapeLayer进行复杂图形绘制的方法,包括路径创建、属性配置及动画实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在ios开发中,也许对于你来说画一条线不难,但是画一个动态线怎么办了,有了UIBezierPath,再也不用担心了

我们从最简单的开始

now!!

layer和bezier路径组成了,我们这次说要学习的主要部分。

layer我们主要用CAShapeLayer;

初始化一下:

roundLayer = [CAShapeLayer new];
        
roundLayer.strokeColor = [UIColor orangeColor].CGColor;
        
roundLayer.fillColor = [UIColor whiteColor].CGColor;
        
roundLayer.lineWidth = 5.0;
        
roundLayer.lineCap = kCALineCapButt;
        
roundLayer.strokeStart = 0.0;
        
roundLayer.bounds = self.bounds;
初始化路径:

m_path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(radius, radius) radius:radius startAngle:0 endAngle: M_PI - M_PI_2 clockwise:NO];

然后将该路径附给layer的路径

roundLayer.path = m_path.CGPath;

到此为止,让我们看一下效果:


很奇怪吧,发现在左上角,完全不是我们我们要的其实两个属性是决定位置的关键,可以告诉一下大家有关layer位置的计算公司,如果你对frame理解很深,其实也是可以明白

position和anchor point的关系,计算公式如下:

首先要清楚,UIView的frame属性是由center和bounds属性计算得到的。
frame.origin.x = center.x - bounds.size.width/2.0;
frame.origin.y = center.y - bounds.size.height/2.0;
frame.size = bounds.size;
相对的,身为UIView下级结构的CALayer呢?
CALayer的position(相当于center),bounds,anchorPoint是什么关系呢?
虽然没有frame,但是CALayer的显示(虚拟frame)也是由这些组件算出来的
frame.origin.x = position.x - anchorPoint.x * bounds.size.width/2.0;
frame.origin.y = position.y - anchorPoint.x * bounds.size.height/2.0;
frame.size = bounds.size;

由于anchorpoint的默认是(0.5,0.5)position的位置是(0.0);

计算一下刚才的,你就明白了吧,为什么在左上角,ok,那么调整一下位置,我们可以调整position或者anchorpoint,

很多人会还是不理解这两个属性的关系,其实position是相对anchorPoint来说的,在锚点的基础上移动的位置就是position,所以移动位置由破尸体哦了决定,anchorpoint只是决定了从哪个点开始计算而已。

如果晕,很正常,记住公式可能更加清楚。锚点还决定了你一些动画旋转的中心,

我们改动下代码,看看效果


roundLayer.anchorPoint = CGPointMake(0, 0);

ok,这样就是完美的那!

讲解下属性吧:可能不全,但是一些常用的会讲,本身贝塞儿的api比较少,全部弄明白也花不了什么时间。


strokeColor和Fillcolor就不说了,可以自己查查资料,两者的区别,linewidth看字面意思,就是线宽,你用shape layer的线的宽度,line cap,这个很有意思,我们查看api有枚举了3种,有一种和其他两种明显不同kCALineJoinRound,这个是两头有一定的圆角弧度,但是其他两种,就比较相似了。貌似没什么区别,nonono,让我们看下苹果官方的解释,两者还是有区别的,一种没有起始连接点,还有一个有,但是外观都一样,按照各自的情况用就可以了。连接点一般你用不到,但是你用到下面哪个属性lineDashPhase就会发现,只有第一种方式才能绘制出正确的虚线,因为下面两种都有连接点,不管怎么样,都会把附近的线连接起来,如果画虚线,注意选择第一种方式哦。但是,如果你设置的虚线空格长度大于了线框,那么也是连接不起来的,因为实在太远了,这可能是苹果的机制吧,如果你画虚线没有绘制的部分长度小于线框,那么就连接起来了。


strokeStart,这个属性很有趣,利用这个属性,我们可以做一些动画,与之对应的还有strokeEnd。记住了默认是0.0,end是1.0。稍后我们会继续讲到这两个属性,

好了layer的属性差不多了,还有两个是linejoin以及lineDashPhase

为了方便讲解,我们以线的例子来说明

我们把创建弧形的代码去掉,换成以下代码:

UIBezierPath  *path = [UIBezierPath bezierPath];
        [path moveToPoint:CGPointMake(0, 0)];
        [path addLineToPoint:CGPointMake(20, 0)];
        [path addLineToPoint:CGPointMake(20, 20)];
        [path stroke];

然后将roundlayer.path = path.cgpath;

我们分别看下3种枚举下

尖脚,拐角

roundLayer.lineJoin = @"miter";


斜角,拐角

roundLayer.lineJoin = @"bevel";



圆角,拐角

roundLayer.lineJoin = @"round";



roundLayer.lineDashPhase = 2;
        
roundLayer.lineDashPattern = [NSArray arrayWithObjects:@5,@5, nil];

lineDashPhase默认是0,如果设置,表示第一个绘制的长度,我原本设置为5绘制5空格,如果设置了lineDashPhase,那么第一段绘制为5-2,然后空5绘制5


讲到这里属性基本差不多了,剩下的一些可以自己探讨一下,那么那两个strokeStart和End,也就放在这里将把,

我们首先绘制一条直线:如图,此时设置strokeStart = 0.0;


然后我们将它设置为0.5,发现变化没?


也就是说start应该0.0,如果一旦设置为大于0.0值,那么只绘制从该值到结束的那一段,打个比方,这条直线我分成10段,如果我start0,end1,那么10段就全部绘制,如果我start设置为5,那么只会绘制6,7,8,9,10这几个,懂了没?


ok,其他一些路径我不一一阐述了,

+ (UIBezierPath *)bezierPathWithRect:(CGRect)rect;
+ (UIBezierPath *)bezierPathWithOvalInRect:(CGRect)rect;
+ (UIBezierPath *)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius; // rounds all corners with the same horizontal and vertical radius
+ (UIBezierPath *)bezierPathWithRoundedRect:(CGRect)rect byRoundingCorners:(UIRectCorner)corners cornerRadii:(CGSize)cornerRadii;
+ (UIBezierPath *)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;
+ (UIBezierPath *)bezierPathWithCGPath:(CGPathRef)CGPath

这些要么画一个圆,要么画一个矩形,其实再熟悉不过了,我们要详细讲讲另外两个画曲线的方法。

- (void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2;
- (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint;

两张图,让你瞬间明白这两个api




ok,当控制点和双控制点很清楚了吧,对应到api里面,一目了然。

讲了这么多,其实感觉有点论,下此博客,我讲以几个例子来讲述这个东西的强大,结合动画,做出你想要的效果,下次见。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值