在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里面,一目了然。
讲了这么多,其实感觉有点论,下此博客,我讲以几个例子来讲述这个东西的强大,结合动画,做出你想要的效果,下次见。