您的位置:首页 > 移动开发 > IOS开发

IOS Dev Intro - Coordination System

2016-06-14 14:27 281 查看
在写程序的时候发现,iOS下的坐标、位置很容易弄乱,特别是在不同的坐标系统中,必须完成弄明白一些概念才能做相应的变化,例如CoreImage和UIView的坐标系统就截然不同,一个是以屏幕的左上角为原点,一个是以屏幕的左下角为原点。总体上,IOS中包含UIKit坐标系(X轴正方向向右,Y轴正方向向下)和标准的Quartz 2D绘图坐标系(X轴正方向向右,Y轴正方向向上),下面,解释一些相关的概念:

一、UIView的bounds属性

定义了一个矩形,描述了一个UIView的位置和大小,注意,其参照系统是自身,所以bounds.origin属性默认是(0, 0),而bounds.size的和frame.size是一致的,该属性主要用在与视图绘制有关的方法中。所有绘制在bounds的范围内的的东西都是该视图的可见内容,如果更改了bounds.origin的位置,那么绘制在新位置的东西将会成为视图新的可见内容(bounds.origin会不会一直还是0,0?)

二、UIView的frame属性

同样也是定义了一个矩形,描述一个UIView的大小和位置,但与bounds属性不同,其参照系统是其父视图(superview)的坐标系统。该属性主要用在控制视图的几何变换中(如视图位置改变、大小改变)。

三、UIView的center属性

该属性用于确定一个视图的中心点位置,其参照系和frame属性一样,是其父视图的坐标系统。该属性的一个作用是对视图进行放大、缩小或旋转时,该属性的值不会变,所以可以用来控制视图的位置。反而,如果使用frame属性的话,该属性下的origin和size的值是会变化的,所以当视图发生变化时,难以用来控制视图的位置。



四、一些特性

1、改变frame属性会同时影响bounds属性和center属性

2、改变center属性会影响frame属性的origin值

3、改变bounds属性的size值会影响frame属性的size值(bounds属性的origin属性呢?待做一下实验)

4、关于视图剪切的说明,如果子视图有部分超出了父视图,那么超出部分同样会被绘制,除非父视图设置了clipsToBounds属性;同时,无论如何,子视图超出父视图的那一部分,都不会响应该子视图的触碰事件。

5、坐标系统的转换:可以通过仿射转换(Affine Transform)来对一个视图的坐标系统进行一些变换,从而实现视图的缩放、旋转等功能,但要注意两点,所有对某一个视图的仿射转换都是针对其center为参照的;二是仿射转换虽然可以改变视图的大小和方向等,但都是针对其父视图而言的,对于应用了仿射的视图来说,实际上是定义了一种坐标对应的变换关系,也就是说,它的frame等属性实际上并没有改变(待做实验)。因此,一些位置、大小等持久化的改变不宜用仿射变换来实现,还是应当通过改变frame属性、center属性等方式来实现。但临时的变换,如制作旋转动画,使用仿射转换都是一个不错的选择。

仿射变换的两种实现方式:

(1)对整个视图应用变换,可以使用视图的setTransForm:方法。

(2)对视图的局部绘制做变换,可以使用视图的drawRect: 方法,前提是先对相应的图形上下文( Graphics Context)进行变换。此外,使用视图的drawRect方法还有一个作用,就是用它来实现视图的位置或大小改变。我们只要指定一中转换关系,在指定的位置绘制视图,就可以达到改变视图大小和位置的相同效果,而且这样做效率还更高。同时,应为drawRect方法应用的是视图的bounds属性,永远是从坐标零点开始绘制,所以使用起来也更加的简便。下面是关于仿射变换的两张图,有助于理解:





==============================================================================================

UIView上的坐标系统

    1.首先左上角为坐标原点(0,0)
    2.CGPoint创建坐标点也就是位置
    3.CGSize表示试图宽度和高度
    4.CGRect结合了CGPoint和CGSize
    5.origin表示右上角所在的CGPoint
    6.frame是在父视图的CGRect
    7.bounds是指在自身视图中的CGRect
    8.center是指在父视图中的CGPoint

Cocos2D上的坐标系统
     1.首先右下角为坐标原点(0,0)
     2.anchorPoint绝对中心点(0.5,0.5)
     3.bounds和frame相同
     4.position就是CGPoint
    

从UITouch对象获得在Cocos2d坐标系中的触摸位置(相对坐标)
- (CGPoint)convertTouchToNodeSpace:(UITouch *)touch
{
//uiLocation:UIKit坐标系表示的相对坐标值( 以屏幕左上角为原点,Y轴向下,X轴向右)
    CGPoint uiLocation = [touch locationInView:[touch view]]; 
//worldLocation:OpenGL坐标系表示的绝对坐标值(以屏幕左下角为原点,Y轴向上,X轴向右)
    CGPoint worldLocation = [[CCDirector sharedDirector] convertToGL:uiLocation];
//localLocation:OpenGL坐标系表示的相对坐标值(以父节点anchorPoint为原点,Y轴向上,X轴向右)
    CGPoint localLocation = [self convertToNodeSpace:worldLocation];
    return localLocation; // coordinate relative to node's parent
}
//父节点的anchorPoint在"父节点的父节点中的相对坐标值":self.parent.anchorPointInPoints

==============================================================================

不同坐标系的介绍

笛卡尔坐标系



UI坐标系

在ios、安卓、wp一般的UI坐标布局中

原点是在左上角

x从左到右递增

y从顶到底递增

像这样



Direct3d

DirectX中采取了笛卡尔左手坐标系

OpenGl和Cocos2d

采用了笛卡尔右手坐标系



在2d中,我们只是用2d的场景

如下:



Parent和Childrens

每个继承自CCNode的子类都有一个anchorpoint的属性

当决定放置位置和旋转中心时,均是以anchorpoint作为参照的

getVisibleSie,getVisibleOriginvsgetWinSize

得到当前屏幕大小
如何转换坐标

convertToNodeSpace

用于将在屏幕上的绝对位置转换为一个node相对于另一个node的方法

CCPointpoint=node1->convertToNodeSpace(node2->getPosition());

这句代码中,node1相当于父节点,node2相当于子节点node2的坐标根据node1相对改变

convertToWorldSpce

转换为世界坐标

convertToNodeSpaceAR

convertToWorldSpaceAR

这两个方法在转换过程中考虑到了anchorpoint
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: