转载

CoreAnimation的几个知识点

  • 矢量图 vs 栅格图
  • 对于 positionanchorPoint 关系的理解

    Point-based coordinates are used when specifying values that map directly to screen coordinates or must be specified relative to another layer, such as for the layer’s position property. Unit coordinates are used when the value should not be tied to screen coordinates because it is relative to some other value. For example, the layer’s anchorPoint property specifies a point relative to the bounds of the layer itself, which can change. ( Core Animation Programming Guide )

简而言之,anchorPoint是一个点相对于layer本身的bounds而言的单元坐标,它可以改变;而position是layer相对superLayer坐标空间的位置。

以桌子与白纸为例,如果固定图钉在桌上的位置,也就是positon不变,这个时候图钉处在白纸的不同地方就是不同的anchorPoint,相应地也就是不同的frame。另一方面,如果固定图钉在白纸上的位置(没订在桌子上),不管怎么平移白纸,anchorPoint肯定是不变的,但frame肯定是随之变化的

  • useEvenOddFillRule

在看 UCZProgressView 的代码时发现了这么一个 UIBezierPath 的属性,而看起来 CAShapeLayer 也有类似的属性,叫 fillRule ,可以设置为 kCAFillRuleEvenOddkCAFillRuleNonZero 。那这个属性到底是做什么的呢?

解释比较清楚的是一篇关于SVG规范的文章,好在最基本的理论都是相通的。

‘fill-rule’ 属性用于指定使用哪一种算法去判断画布上的某区域是否属于该图形“内部” (内部区域将被填充)。对一个简单的无交叉的路径,哪块区域是“内部” 是很直观清除的。但是,对一个复杂的路径,比如自相交或者一个子路径包围另一个子路径,“内部”的理解就不那么明确了。

nonzero

字面意思是“非零”。按该规则,要判断一个点是否在图形内,从该点作任意方向的一条射线,然后检测射线与图形路径的交点情况。从0开始计数,路径从左向右穿过射线则计数加1,从右向左穿过射线则计数减1。得出计数结果后,如果结果是0,则认为点在图形外部,否则认为在内部。下图演示了nonzero规则:

CoreAnimation的几个知识点

evenodd

字面意思是“奇偶”。按该规则,要判断一个点是否在图形内,从该点作任意方向的一条射线,然后检测射线与图形路径的交点的数量。如果结果是奇数则认为点在内部,是偶数则认为点在外部。下图演示了evenodd 规则:

CoreAnimation的几个知识点

又想到了之前在一个项目中实现的中间有洞的矩形view,翻来瞅一眼。

CAShapeLayer *maskWithHole = [CAShapeLayer layer];  // Both frames are defined in the same coordinate system CGRect biggerRect = CGRectMake(30, 50, 120, 200); CGRect smallerRect = CGRectMake(80, 100, 50, 80);  UIBezierPath *maskPath = [UIBezierPath bezierPath]; [maskPath moveToPoint:CGPointMake(CGRectGetMinX(biggerRect), CGRectGetMinY(biggerRect))]; [maskPath addLineToPoint:CGPointMake(CGRectGetMinX(biggerRect), CGRectGetMaxY(biggerRect))]; [maskPath addLineToPoint:CGPointMake(CGRectGetMaxX(biggerRect), CGRectGetMaxY(biggerRect))]; [maskPath addLineToPoint:CGPointMake(CGRectGetMaxX(biggerRect), CGRectGetMinY(biggerRect))]; [maskPath addLineToPoint:CGPointMake(CGRectGetMinX(biggerRect), CGRectGetMinY(biggerRect))];  [maskPath moveToPoint:CGPointMake(CGRectGetMinX(smallerRect), CGRectGetMinY(smallerRect))]; [maskPath addLineToPoint:CGPointMake(CGRectGetMinX(smallerRect), CGRectGetMaxY(smallerRect))]; [maskPath addLineToPoint:CGPointMake(CGRectGetMaxX(smallerRect), CGRectGetMaxY(smallerRect))]; [maskPath addLineToPoint:CGPointMake(CGRectGetMaxX(smallerRect), CGRectGetMinY(smallerRect))]; [maskPath addLineToPoint:CGPointMake(CGRectGetMinX(smallerRect), CGRectGetMinY(smallerRect))];  [maskWithHole setPath:[maskPath CGPath]]; **[maskWithHole setFillRule:kCAFillRuleEvenOdd];** [maskWithHole setFillColor:[[UIColor orangeColor] CGColor]]; 

所以,为了“有洞”,最重要的是这一行 [maskWithHole setFillRule:kCAFillRuleEvenOdd]; 。如果设置成 kCAFillRuleNonZero (好吧,这个值是默认值),就会得到一个货真价实的实心矩形。当时没有意识到这句话的作用,现在终于明了了。

Ref:

  • Core Animation Programming Guide:
    https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreAnimation_guide/CoreAnimationBasics/CoreAnimationBasics.html#//apple_ref/doc/uid/TP40004514-CH2-SW15
  • http://stackoverflow.com/questions/10856353/crop-a-cashapelayer-retrieving-the-external-path
  • http://blog.csdn.net/cuixiping/article/details/7848369
  • http://stackoverflow.com/questions/14840563/how-does-usesevenoddfillrule-work
原文  http://www.calios.gq/2016/02/29/CoreAnimation的几个知识点/
正文到此结束
Loading...