IOS Core Animation Advanced Techniques的学习笔记(二)

[objc] view plaincopyprint?转载学习

  1. - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
  2. {
  3. CGFloat width = 10.0f;
  4. //draw a thick red circle
  5. CGContextSetLineWidth(ctx, width);
  6. CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor);
  7. CGRect rect = CGRectMake(layer.bounds.origin.x+width/2, layer.bounds.origin.y+width/2, layer.bounds.size.width-width, layer.bounds.size.height-width);
  8. CGContextStrokeEllipseInRect(ctx, rect);
  9. }

接上次,修改了一下,呵呵,看着舒服多了

由此可见线宽的扩展方式是同时向两边扩展的。

第三章:Layer Geometry

 

“Let no one unversed in geometry enter here.”
看到作者的信心了吧,你有了吗?

UIView的布局属性有frame,bounds和center,CALayer同样有3个对应frame,bounds和position。如图:

需要注意的是,frame不是一个独立的属性,它是由bounds,position,transform等其他属性计算而来,所以改变frame会影响其他属性,反之改变其他属性也会影响frame。如果我在前面的例子里增加一行改变frame的代码你会看到如下结果

[objc] view plaincopyprint?

  1. - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
  2. {
  3. CGFloat width = 10.0f;
  4. //draw a thick red circle
  5. CGContextSetLineWidth(ctx, width);
  6. CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor);
  7. CGRect rect = CGRectMake(layer.bounds.origin.x+width/2, layer.bounds.origin.y+width/2, layer.bounds.size.width-width, layer.bounds.size.height-width);
  8. CGContextStrokeEllipseInRect(ctx, rect);
  9. layer.frame = CGRectMake(10.0f, 10.0f, 200.0f, 200.0f);
  10. }

还有需要注意在操作transform时,如旋转时,frame会重新计算,此时frame的宽高不再和bounds比配。如图

下面再说说anchorPoint这个属性,很多人对于使用此属性可能会迷惑,到底是怎么设置的,先看张图

anchorPoint从{0.5, 0.5}变为{0, 0},layer向右下偏移了,下面大家可以用一下做个试验

还是使用上面的例子,在- (void)viewDidLoad的[blueLayerdisplay];前增加

[objc] view plaincopyprint?

  1. NSLog(@"%@", NSStringFromCGPoint(blueLayer.anchorPoint));
  2. NSLog(@"%@", NSStringFromCGPoint(blueLayer.position));

是为了记录变化前的值,接着在- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx中

增加对anchorPoint的设置,自已可以任意设置看看结果

[objc] view plaincopyprint?

  1. - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
  2. {
  3. CGFloat width = 10.0f;
  4. //draw a thick red circle
  5. CGContextSetLineWidth(ctx, width);
  6. CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor);
  7. CGRect rect = CGRectMake(layer.bounds.origin.x+width/2, layer.bounds.origin.y+width/2, layer.bounds.size.width-width, layer.bounds.size.height-width);
  8. CGContextStrokeEllipseInRect(ctx, rect);
  9. layer.anchorPoint = CGPointMake(0, 0);
  10. NSLog(@"%@", NSStringFromCGPoint(layer.position));
  11. }

我们可以得出结论,anchorPoint可以简单地看作是设置左上顶点相对于中心position的位置,

计数以左上顶点到position的距离与宽高的比例,X轴方向正为左移负为右移,Y轴方向正为上移负为下移。

下面我们用例子来看看具体的应用,具体代码请查看例子3.1

源码在这里下载:http://www.informit.com/title/9780133440751

[objc] view plaincopyprint?

  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4. //start timer
  5. self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0
  6. target:self
  7. selector:@selector(tick)
  8. userInfo:nil
  9. repeats:YES];
  10. //set initial hand positions
  11. [self tick];
  12. }
  13. - (void)tick
  14. {
  15. //convert time to hours, minutes and seconds
  16. NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
  17. NSUInteger units = NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
  18. NSDateComponents *components = [calendar components:units fromDate:[NSDate date]];
  19. //calculate hour hand angle
  20. CGFloat hourAngle = (components.hour / 12.0) * M_PI * 2.0;
  21. //calculate minute hand angle
  22. CGFloat minuteAngle = (components.minute / 60.0) * M_PI * 2.0;
  23. //calculate second hand angle
  24. CGFloat secondAngle = (components.second / 60.0) * M_PI * 2.0;
  25. //rotate hands
  26. self.hourHand.transform = CGAffineTransformMakeRotation(hourAngle);
  27. self.minuteHand.transform = CGAffineTransformMakeRotation(minuteAngle);
  28. self.secondHand.transform = CGAffineTransformMakeRotation(secondAngle);
  29. }

运行看看结果

发现什么了没有?CGAffineTransformMakeRotation以View的center点在旋转

再看例子3.2,修改代码

[objc] view plaincopyprint?

  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4. //adjust anchor points
  5. self.secondHand.layer.anchorPoint = CGPointMake(0.5f, 0.9f); // 为什么不是1.0f?
  6. self.minuteHand.layer.anchorPoint = CGPointMake(0.5f, 0.9f);
  7. self.hourHand.layer.anchorPoint = CGPointMake(0.5f, 0.9f);
  8. //start timer
  9. self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0
  10. target:self
  11. selector:@selector(tick)
  12. userInfo:nil
  13. repeats:YES];
  14. //set initial hand positions
  15. [self tick];
  16. }

看结果

CGAffineTransformMakeRotation以layer的position点在旋转

相对坐标的转换函数,UIView使用:

- (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view;

- (CGPoint)convertPoint:(CGPoint)point fromView:(UIView *)view;

- (CGRect)convertRect:(CGRect)rect toView:(UIView *)view;

- (CGRect)convertRect:(CGRect)rect fromView:(UIView *)view;

CALayer使用:

- (CGPoint)convertPoint:(CGPoint)p fromLayer:(CALayer *)l;

- (CGPoint)convertPoint:(CGPoint)p toLayer:(CALayer *)l;

- (CGRect)convertRect:(CGRect)r fromLayer:(CALayer *)l;

- (CGRect)convertRect:(CGRect)r toLayer:(CALayer *)l;

注意:直到OS X 10.8才出现了geometryFlipped属性,该属性可以改变默认图层y坐标的方向。当翻转变换被调用时,使用该属性来调整图层的方向有的时候是必需的。如果父视图使用了翻转变换,它的子视图内容(以及它对应的图层)将经常被颠倒。在这种情况下,设置子图层的geometryFlipped属性为YES是一种修正该问题最简单的方法。在OS X 10.8及以上版本,AppKit负责管理该属性,你不应该更改它。对于iOS app,不推荐使用geometryFlipped属性。

“This is a BOOL value that determines whether the geometry of a layer is vertically flipped with respect to its superlayer. Setting this property to YES for a layer on iOS means that its sublayers will be flipped vertically and will be positioned relative to the bottom of its bounds rather than the top as normal (as will all of their sublayers, and so on, unless they also have YES for their geometryFlipped property).”
注意的是geometryFlipped只对sublayers起作用,只到有sub也设置了YES才恢复,有点负负得正的意思

修改例子3.2代码

[objc] view plaincopyprint?

  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4. //adjust anchor points
  5. self.view.layer.geometryFlipped = YES;
  6. self.secondHand.layer.anchorPoint = CGPointMake(0.5f, 0.9f);
  7. self.minuteHand.layer.anchorPoint = CGPointMake(0.5f, 0.9f);
  8. self.hourHand.layer.anchorPoint = CGPointMake(0.5f, 0.9f);
  9. //start timer
  10. self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0
  11. target:self
  12. selector:@selector(tick)
  13. userInfo:nil
  14. repeats:YES];
  15. //set initial hand positions
  16. [self tick];
  17. }

自己运行看看,指针反着转了。

再修改看看的geometryFlipped sublayers的作用域,呵呵暂且这么说
首先增加一个view作为secondHand的父view,修改代码

增加

[objc] view plaincopyprint?

  1. @property (weak, nonatomic) IBOutlet UIView *sView;

[objc] view plaincopyprint?

  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4. //adjust anchor points
  5. self.view.layer.geometryFlipped = YES;
  6. self.sView.layer.geometryFlipped = YES;
  7. self.secondHand.layer.anchorPoint = CGPointMake(0.5f, 0.9f);
  8. self.minuteHand.layer.anchorPoint = CGPointMake(0.5f, 0.9f);
  9. self.hourHand.layer.anchorPoint = CGPointMake(0.5f, 0.9f);
  10. //start timer
  11. self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0
  12. target:self
  13. selector:@selector(tick)
  14. userInfo:nil
  15. repeats:YES];
  16. //set initial hand positions
  17. [self tick];
  18. }

看结果

秒针正常了

我们以前接触的UIView是2维坐标,但现在CAlayer确实3维坐标,增加了Z轴, zPosition 和 anchorPointZ
看例子3.3,zPosition默认值为0,当设置self.greenView.layer.zPosition大于0时,greenView将遮盖redView

运行结果

例子3.4和3.5是对

[objc] view plaincopyprint?

  1. /* Returns the farthest descendant of the layer containing point ‘p‘.
  2. * Siblings are searched in top-to-bottom order. ‘p‘ is defined to be
  3. * in the coordinate space of the receiver‘s nearest ancestor that
  4. * isn‘t a CATransformLayer (transform layers don‘t have a 2D
  5. * coordinate space in which the point could be specified). */
  6. - (CALayer *)hitTest:(CGPoint)p;
  7. /* Returns true if the bounds of the layer contains point ‘p‘. */
  8. - (BOOL)containsPoint:(CGPoint)p;

两个函数的,自己去看

时间: 2024-10-20 17:41:04

IOS Core Animation Advanced Techniques的学习笔记(二)的相关文章

IOS Core Animation Advanced Techniques的学习笔记(一)

转载. Book Description Publication Date: August 12, 2013 Core Animation is the technology underlying Apple’s iOS user interface. By unleashing the full power of Core Animation, you can enhance your app with impressive 2D and 3D visual effects and creat

IOS Core Animation Advanced Techniques的学习笔记(五)

第六章:Specialized Layers   类别 用途 CAEmitterLayer 用于实现基于Core Animation粒子发射系统.发射器层对象控制粒子的生成和起源 CAGradientLayer 用于绘制一个颜色渐变填充图层的形状(所有圆角矩形边界内的部分) CAEAGLLayer/CAOpenGLLayer 用于设置需要使用OpenGL ES(iOS)或OpenGL(OS X)绘制的内容与内容储备. CAReplicatorLayer 当你想自动生成一个或多个子层的拷贝.复制器

IOS Core Animation Advanced Techniques的学习笔记(四)

第五章:Transforms Affine Transforms CGAffineTransform是二维的 Creating a CGAffineTransform 主要有三种变化方法 旋转: CGAffineTransformMakeRotation(CGFloat angle) 缩放: CGAffineTransformMakeScale(CGFloat sx, CGFloat sy) 移动: CGAffineTransformMakeTranslation(CGFloat tx, CGF

IOS Core Animation Advanced Techniques的学习笔记(三)

第四章:Visual Effects   Rounded Corners 例子4.1 cornerRadius 源码在这里下载:http://www.informit.com/title/9780133440751 [objc] view plaincopyprint? #import "ViewController.h" #import <QuartzCore/QuartzCore.h> @interface ViewController () @property (no

iOS Core Animation Advanced Techniques(四):隐式动画和显式动画

隐式动画 按照我的意思去做,而不是我说的. -- 埃德娜,辛普森 我们在第一部分讨论了Core Animation除了动画之外可以做到的任何事情.但是动画师Core Animation库一个非常显著的特性.这一章我们来看看它是怎么做到的.具体来说,我们先来讨论框架自动完成的隐式动画(除非你明确禁用了这个功能). 事务 Core Animation基于一个假设,说屏幕上的任何东西都可以(或者可能)做动画.动画并不需要你在Core Animation中手动打开,相反需要明确地关闭,否则他会一直存在.

iOS Core Animation Advanced Techniques(六): 基于定时器的动画和性能调优

基于定时器的动画 我可以指导你,但是你必须按照我说的做. -- 骇客帝国 在第10章“缓冲”中,我们研究了CAMediaTimingFunction,它是一个通过控制动画缓冲来模拟物理效果例如加速或者减速来增强现实感的东西,那么如果想更加真实地模拟 物理交互或者实时根据用户输入修改动画改怎么办呢?在这一章中,我们将继续探索一种能够允许我们精确地控制一帧一帧展示的基于定时器的动画. 定时帧 动画看起来是用来显示一段连续的运动过程,但实际上当在固定位置上展示像素的时候并不能做到这一点.一般来说这种显

iOS Core Animation Advanced Techniques(三):专用图层

到目前为止,我们已经探讨过CALayer类了,同时我们也了解到了一些非常有用的绘图和动画功能.但是Core Animation图层不仅仅能作用于图片和颜色而已.本章就会学习其他的一些图层类,进一步扩展使用Core Animation绘图的能力. CAShapeLayer 在第四章『视觉效果』我们学习到了不使用图片的情况下用CGPath去构造任意形状的阴影.如果我们能用同样的方式创建相同形状的图层就好了. CAShapeLayer是一个通过矢量图形而不是bitmap来绘制的图层子类.你指定诸如颜色

iOS Core Animation Advanced Techniques(七):高效绘图、图像IO以及图层性能

高效绘图不必要的效率考虑往往是性能问题的万恶之源. ——William Allan Wulf 在第12章『速度的曲率』我们学习如何用Instruments来诊断Core Animation性能问题.在构建一个iOS app的时候会遇到很多潜在的性能陷阱,但是在本章我们将着眼于有关绘制的性能问题. 软件绘图 术语绘图通常在Core Animation的上下文中指代软件绘图(意即:不由GPU协助的绘图).在iOS中,软件绘图通常是由Core Graphics框架完成来完成.但是,在一些必要的情况下,

iOS Core Animation Advanced Techniques(二):视觉效果和变换

四)视觉效果 嗯,园和椭圆还不错,但如果是带圆角的矩形呢? 我们现在能做到那样了么? 史蒂芬·乔布斯 我们在第三章『图层几何学』中讨论了图层的frame,第二章『寄宿图』则讨论了图层的寄宿图.但是图层不仅仅可以是图片或是颜色的容器:还有一系列内建的特性使得创造美丽优雅的令人深刻的界面元素成为可能.在这一章,我们将会探索一些能够通过使用CALayer属性实现的视觉效果. 圆角 圆角矩形是iOS的一个标志性审美特性.这在iOS的每一个地方都得到了体现,不论是主屏幕图标,还是警告弹框,甚至是文本框.按