iOS核心动画笔记4-图形几何学

半腔热情 提交于 2020-03-01 02:51:26

图层几何学

1. 布局

UIView有三个比较重要的属性: frame, bounds, center. CALayer对应的叫做: frame,bounds,position. frame代表图层外部坐标, bounds是内部坐标.

视图的frame, bounds, center属性仅仅是存取方法, 当操作视图的frame时候,实际上是改变位于视图下方CALayer的frame, 不能独立于图层之外改变视图的frame. 对于视图和图层来说, frame并不是一个非常清晰的属性,他其实是一个虚拟的属性, 是根据bounds, position和transform计算而来的, 当其中任意一值发生变化, frame都会变化, 同样的, frame也会影响到他们当中的值.

当图层做变换时候, 比如旋转或者缩放, frame实际上代表的是覆盖在图层旋转之后的整个轴对称对齐的矩形区域, 就是说, frame和bounds宽高不再保持一致.

2. 锚点

anchorPoint默认位于图层的中点, 所以图层将会以这个点为中心放置. 图层的anchorPoint是可以被移动的, 比如当把它置于图层frame的左上角, 于是图层内容将会向右下角的Position方向移动.

anchorPoint也使用单位坐标来描述. 当改变anchorPoint时候, Position属性保持固定, 但是frame却会发生变化.

一个移动anchorPoint而不该表frame的方法:

简单地说, 就是改变Position, 测试发现, 例如, 将anchorPoint移动到左上角, 正常情况下, frame会向右下角移动0.5的单位, 如果改变anchorPoint的同时, 更改Position, Position的向左上角移动0.5*frame.size.width, 这时候, frame看起来就是不动的.

不过这点关系, 还是有点迷糊.....

3. 坐标系

CALayer给不同坐标系之间的图层转换提供了一些工具类方法, 类似于视图之间坐标系的转换方法:

- (CGPoint)convertPoint:(CGPoint)point fromLayer:(CALayer *)layer; 
- (CGPoint)convertPoint:(CGPoint)point toLayer:(CALayer *)layer; 
- (CGRect)convertRect:(CGRect)rect fromLayer:(CALayer *)layer;
- (CGRect)convertRect:(CGRect)rect toLayer:(CALayer *)layer;

4. z坐标轴

UIView位于严格的二维坐标系中, CALayer存在于三维空间中, 它的aPosition和anchorPointZ都是在z轴上面描述图层位置的浮点类型. zPosition在大多数情况下不常用, 它的主要功能就是改变图层的显示顺序.

最好使用图层相关的视图, 而不直接使用图层, 主要原因是因为要处理额外的复杂的触摸事件. CALayer并不关心任何响应链事件, 所以不能直接处理触摸事件或者手势. 但是它也有几个方法可以帮你处理事件: -containsPoint:和-hitTest:

-containsPoint: 接受一个在本图层坐标系下的CGPoint, 如果点在bounds内, 返回YES. 缺点是, 如果使用这种方法, 需要将发生事件的位置, 转换到每一个layer坐标系当中去, 不方便.

-hitTest: 同样接受一个CGPoint类型参数, 返回值是图层本身, 既发生点击事件的图层. 如果点不在此图层树范围内, 则返回nil.

code:

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    
    //获取发生在view上的一个点
    CGPoint point = [[touches anyObject] locationInView:self.view];
    
    //通过hitTest方法找到点在哪个layer上面. 返回值是CALayer对象, UIView也有相关的方法
    CALayer *targetLayer = [self.view.layer hitTest:point];
    
    if (targetLayer == self.greenLayer) {
        NSLog(@"绿色 layer");
    }
    if (targetLayer == self.redLayer) {
        NSLog(@"红色 layer");
    }

}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!