《iOS Drawing Practical UIKit Solutions》读书笔记(二) —— The Language of Geometry

Points VS Pixels

Point是UIKit中的逻辑位置,并不代表像素。主要是在Retina屏幕中,一个Point会对应2或3个Pixels,这取决于PPI(DPI):pixel per inch ,像素密度PPI,指每英尺的像素数,表示了清晰度。

这里写图片描述

Scale

UIScreen类的属性scale, 表明了当前设备点与像素间的关系。因此,对于非Retain屏,scale == 1.0 ,而Retain屏则是2.0 或 3.0 。

UIScreen提供两种属性来表示display-size:
1. bounds : 表示Screen的bounding,以Point为单位,表示整个屏幕的大小。
2. applicationFrame: 表示实际可用屏幕的Frame,这是除掉status bars,navigation bars 或 tab bars的大小。

View Coordinates

在iOS 7及以后,view的坐标原点一般都是在navigation bar下面开始。这取决于VC的edgesForExtendedLayout属性设置。

Coordinate System之间的转换

我们说所的Frame,Point,都是基于一个UIView中的坐标系统来说的。如果想在UIView之间转换坐标值使得在另一个UIView中定位同样的位置,iOS SDK 提供了一系列
toView, fromView方法。

注意,View之间的坐标转换是针对于位于同一个UIWIndow中的View来说的,只要位于一个View,就可以进行坐标的转换,而View之间不必有父子关系。

Key Structures

iOS 用四种主要的数据结构来描述几何信息,分别是:

  • CGPoint
  • CGSize
  • CGRect
  • CGAffineTransform
    仿射变换,代表了a,b,c,d,tx和ty矩阵。
    这里写图片描述

输出Transforms

UIKit默认给出方法

NSStringFromCGAffineTransform()
CGAffineTransformFromString()

来使得NSString 和 CGAffineTransform之前转换,但输出的内容并不直观:
这里写图片描述

我们可以用如下的函数来计算Scale和Rotate的数值:

CGFloat TransformGetXScale(CGAffineTransform t) {
    return sqrt(t.a * t.a + t.c * t.c);
}

CGFloat TransformGetYScale(CGAffineTransform t) {
    return sqrt(t.b * t.b + t.d * t.d);
}

CGFloat TransformGetRotation(CGAffineTransform t) {
    return atan2f(t.b, t.a);
}

预定义常量

这里写图片描述
这里写图片描述

Conversion to Objects

由于所有的几何对象都是以struct的形式,所以为了支持Object的方法,Core Graphics和Core Foundation均提供了若干函数将几何对象转换为真正的Object对象。
可以转换为的对象是:
1. Strings
2. Dictionaries
3. Vaules

String

这里写图片描述

Dictionaries

注意,这里转换的Dictionary是CFDictionaryRef,需要bridge到NSDictionary
这里写图片描述

Value

NSValue为C类型的数据提供了一个面向对象的容器。它可以包含标量类型(int, float),指针和结构体。UIKit扩展了NSVaule,使之能够接受Core Graphics数据。
这里写图片描述

这里写图片描述

Geometry Tests

Core Graphics提供了一系列函数,可以对几何数据类型进行测试:
这里写图片描述
这里写图片描述

这里写图片描述
这里写图片描述

Rectangle 工具方法

针对CGRect结构,下面补充了一些工具方法,可用于平常开发时使用
1. 创建Rect

CGRect RectMakeRect(CGPoint origin, CGSize size) {
    return (CGRect){.origin = origin, .size = size};
}
  1. 获取Rect 的 Center Point
CGRect RectGetCenter(CGRect rect) {
    return CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
}
  1. 创建一个指定center point, size的Rect
CGRect RectAroundCenter(CGPoint center, CGSize size) {
    CGFloat halfWidth = size.width / 2.0f;
    CGFloat halfHeight = size.height / 2.0f;
    return CGRectMake(center.x - halfWidth, center.y - halfHeight, size.width, size.height);
}

Fitting and Filling

有时候我们需要调整对象的大小,来让它draw到比实际内容要大(小)的空间中。
常用的方法有:
1. centering
2. fitting
3. filling
4. squeezing

Centering

Centering的内容会显示在矩形的正中,同时按照原始大小显示。对于大出的部分,会被裁掉,而小的部分,其余会默认填充灰色。

这里写图片描述

Fitting

Fitting意味着展示的内容会按照原比例压缩(或放大),其余的地方则会留空。

如图
这里写图片描述

CGSize SizeScaleByFactor(CGSize aSize, CGFloat factor) {
    return CGSizeMake(aSize.width * factor, aSize.height * factor);
}

CGFloat AspectScaleFit(CGSize sourceSize, CGRect destRect) {
    CGSize destSize = destRect.size;
    CGFloat scaleW = destSize.width / sourceSize.width;
    CGFloat scaleH = destSize.height / sourceSize.height;
    return MIN(scaleW, scaleH);
}

CGRect RectByFittingInRect(CGRect sourceRect, CGRect destinationRect){
    CGFloat aspect = AspectScaleFit(sourceRect.size, destinationRect);
    CGFloat targetSize = SizeScaleByFactor(sourceRect.size, aspect);
    return RectAroundCenter(RectGetCenter(destinationRect), targetSize);
}

Filling

Filling 如图所示,它会保证每一个像素都会对应到目标空间的对应位置,但是却不能保证图片被显示完全。为了实现像素到目标空间的对应,原始图片会被拉伸或缩小。

这里写图片描述

CGSize SizeScaleByFactor(CGSize aSize, CGFloat factor) {
    return CGSizeMake(aSize.width * factor, aSize.height * factor);
}

CGFloat AspectScaleFill(CGSize soruceSize, CGRect destRect){
    CGSize destSize = destRect.size;
    CGFloat scaleW = destSize.width / sourceSize.width;
    CGFloat scaleH = destSize.height / sourceSize.height;
    return MAX(scaleW, scaleH);
}

CGRect RectByFillingRect(CGRect sourceRect, CGRect destinationRect){
    CGFloat aspect = AspectScaleFill(sourceRect.size, destinationRect);
    CGFloat targetSize = SizeScaleByFactor(sourceRect.size, aspect);
    return RectAroundCenter(RectGetCenter(destinationRect), targetSize);
}

Squeezing

Squeezing会调整原始图像的大小与比例,使之能够在目标空间中显示出来。我们不需要对原始图像做任何调整,只需要将其draw到目的空间中,Quartz会做剩余的事情。
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值