iOS像素与点

作者: 小黑_Coder | 来源:发表于2017-01-10 00:49 被阅读410次

iOS上的像素(Pixel)与点(Point)

像素(Pixel)和点(Point)

我们在讨论这个问题之前,最起码要搞懂什么是点(Point)和什么是(Pixel)这个几个概念

  • px:pixel像素,屏幕上显示的最小单位
  • pt:point点,是一个标准的长度单位,1pt=1/72inch
  • PPI(DPI):pixel per inch像素密度PPI,指每英尺的像素数,表示了清晰度

1inch=2.54cm =25.4mm

好概念就普及到这里了因为在装下去就要露馅了,今天有空为什么要说一说像素和点呢?因为在设计师验收的时候发现不合格(ps:自己都看不下去了),既然已经踩了坑,那就把过坑的方法拿出来分享一下吧(PS:鄙人学识短浅,哪有说的不对的地方还望大牛们多多指点)。

Xib带来的一点坑

场景

设计师经常喜欢在用户名,密码等输入框下面给一个高度为1px的下划线。这个时候对于开发人员来讲可能直接使用约束在输入框下面添加一个view然后修改背景颜色,此时我们就顺利入坑了。

xib.png

看上去好像是达到了我们预期的效果。我们这时在使用代码来实现一下。

//代码实现方式一
       for i in 0 ..< 5 {
            
           let view = UIView.init(frame: CGRect.init(x: 0, y: 200+CGFloat(i)*10, width: self.view.frame.width, height: 0.5))
           view.backgroundColor = UIColor.init(colorLiteralRed: 207.0/255.0, green: 181.0/255.0, blue: 107.0/255.0, alpha: 1)
           self.view.addSubview(view)
       }
        
//代码实现方式二
       for i in 0 ..< 5 {
            
           let view = UIView.init(frame: CGRect.init(x: 0, y: 300+CGFloat(i)*10, width: self.view.frame.width, height: 1.0/UIScreen.main.scale))
           view.backgroundColor = UIColor.init(colorLiteralRed: 207.0/255.0, green: 181.0/255.0, blue: 107.0/255.0, alpha: 1)
           self.view.addSubview(view)
        } 

效果

iPhone 7上实验了一下,结果却并不是我们想要的

result1.PNG

对比发现Xib实现的下划线存在有点的变粗有点变细,这一点对于设计师当然是不能忍受的。当然非要使用Xib来完成这一项需求也是可以的,我们可以把xib中的约束拖成类的属性,然后使用代码对约束进行修改。这个解决方案我写在了代码中就不在这里详细介绍了,如果感兴趣可以尝试一下,当然个人不推荐使用修改约束的方法。

分析

iOS中,point独立于物理设备的逻辑坐标单位。iPhone 4之前non-retina屏幕的设备,一个point就代表一个像素;从iPhone 4iPhone 7,采用retina屏幕;一个point,代表2X2个像素;Plus的设备,一个point代表3X3个像素。

  • 绘图系统通常都会采用一个叫反锯齿antialiasing的技术,iOS也不例外。我们前面提到过像素是屏幕上显示的最小单位。屏幕有很多小的显示单元组成,简单理解一个单元就代表一个像素。如果要画一条黑线,条线刚好落在了一列或者一行显示单元之内,将会渲染出标准的一像素黑线。但如果线落在了两个行或列的中间时,那么会得到一条失真的线,其实是两个像素宽的灰线,我们可以看Apple给出的文档
    图片来自Apple官方文档.png

Positions defined by whole-numbered points fall at the midpoint between pixels. For example, if you draw a one-pixel-wide vertical line from (1.0, 1.0) to (1.0, 10.0), you get a fuzzy grey line. If you draw a two-pixel-wide line, you get a solid black line because it fully covers two pixels (one on either side of the specified point). As a rule, lines that are an odd number of physical pixels wide appear softer than lines with widths measured in even numbers of physical pixels unless you adjust their position to make them cover pixels fully.

  • 一个英语超烂的人读了官方文档以后,加上自己的理解简单翻译如下。

规定:奇数像素宽度的线在渲染的时候将会表现为柔和的宽度扩展到向上的整数宽度的线,除非你手动的调整线的位置,使线刚好落在一行或列的显示单元内。

  • 那么我们该怎么去让线与刚好落在一行或一列的显示单元内,请看官方给我的解决方案

On a low-resolution display (with a scale factor of 1.0), a one-point-wide line is one pixel wide. To avoid antialiasing when you draw a one-point-wide horizontal or vertical line, if the line is an odd number of pixels in width, you must offset the position by 0.5 points to either side of a whole-numbered position. If the line is an even number of points in width, to avoid a fuzzy line, you must not do so.
On a high-resolution display (with a scale factor of 2.0), a line that is one point wide is not antialiased at all because it occupies two full pixels (from -0.5 to +0.5). To draw a line that covers only a single physical pixel, you would need to make it 0.5 points in thickness and offset its position by 0.25 points. A comparison between the two types of screens is shown in Figure 1-4.

  • 没有自知之明的我,看完文档以后依然加上自己的理解给出了一个简单的翻译

在非高清屏上,一个Point对应一个像素。为了防止antialiasing导致的奇数像素的线渲染时出现失真,你需要设置偏移0.5 Point。在高清屏幕上,要绘制一个像素的线,需要设置线宽为0.5 Point,同时设置偏移为0.25 Point。如果线宽为偶数Point的话,则不要去设置偏移,否则线条也会失真。

图片来自Apple官方文档.png
  • 至此问题貌似都解决了,再想想为什么在非RetinaRetina屏幕上调整位置时值不一样,前者为0.5 Point,后者为0.25 Point,那么scale36/7 Plus设备又该调整多少呢?那我们就在回过头来看看下面这幅图,顶部标记为我们代码布局时的坐标。在非`Retina屏幕,我们要在(3,0)这个位置画一条一个像素宽的竖线时,由于渲染的最小单位是像素,而(3,0)这个坐标恰好位于两个像素中间,此时系统会对坐标3左右两列的像素对填充,为了不至于线显得太宽,线的颜色淡化。那么根据上述信息我们可以得出,如果要画出一个像素宽的线,就得把绘制的坐标移动到(2.5, 0)或者(3.5,0)这个位置,这样系统渲染的时候刚好可以填充一列像素,也就是标准的一个像素的线。

    图片来自网络. png
  • 基于上面的分析,我们可以得出“Scale为3的6 Plus”设备如果要绘制1个像素宽的线条时,位置调整也应该是0.5像素,对应该的Point计算如下:

(1.f /UIScreen.main.scale) / 2;

  • 那么为什么在Xib中会出现粗细不一样,而使用代码却可以呢。因为在Xib设置约束之后系统不会因我们设置了奇数个像素点没有落在一行或一列的显示单元内,而给我们调整。但是我们使用代码编写的时候,系统在渲染的时候就会帮我们调整到一行或一列的显示单元内。

最好的学习资料

官方文档:https://developer.apple.com/library/content/documentation/2DDrawing/Conceptual/DrawingPrintingiOS/GraphicsDrawingOverview/GraphicsDrawingOverview.html

欢迎讨论

email:huliuworld@yahoo.com
相关代码:https://github.com/LHCoder2016/PixelAndPoint.git

相关文章

  • iOS像素与点

    iOS上的像素(Pixel)与点(Point) 像素(Pixel)和点(Point) 我们在讨论这个问题之前,最起...

  • appicon

    型号iphone点pt尺寸(像素)尺寸(像素) iphone iPhone Notification iOS 7-...

  • iOS开发之像素与点

    相信iOSer们都被iOS开发中像素和点这两个概念困扰过,经过一段时间的学习和总结,再次为大家讲讲我的个人理解,希...

  • media-像素与屏幕

    Ios尺寸表 1、 piexl 像素知识 逻辑像素与物理像素的关系 px逻辑像素:浏览器使用的抽象单位 dp,pt...

  • iOS 中 pt 与px的区分

    px:像素pt:独立像素 / point / 点 iOS 开发中用到的单位 pt 是独立像素的意思,它是绝对长度,...

  • CRF条件随机场

    每个像素点作为节点,像素与像素间的关系作为边,即构成了一个条件随机场。通过二元势函数描述像素点与像素点之间的关系,...

  • IOS --- 字体

    ios 字体与px单位字体的换算<网络图> ios屏幕像素一览表

  • iOS图片与像素

    我们知道图片的格式有很多种,如主流的png,jpg。这些格式指什么呢,指的是对图片的bitemap裸数据的压缩格式...

  • Android和IOS使用的尺寸单位

    IOS px:像素 ppi:pixels per inch,每英寸像素数 pt:point,ios开发使用的单位 ...

  • 图片切割 (给定一张图片, 截取指定区域范围内的图片,给图片添加

    注意:1.CGImageCreateWithImageInRect 使用的坐标都是像素点2.iOS使用的都是点坐标...

网友评论

  • 我只是个仙:没看太懂 ,而且感觉没头没尾的,最后到底是怎么解决的呢?
  • 郑一一一一:由于渲染的最小单位是像素,而(3,0)这个坐标恰好位于两个像素中间,此时系统会对坐标3左右两列的像素对填充,为了不至于线显得太宽,线的颜色淡化。这句话实在不懂!
  • 郑一一一一:有些地方 看不懂。
    小黑_Coder:@啊啦哈 可以提出来我们在探讨一下哦
  • 秋_明:这个点确实是的
  • 山水域:二货,英语有进步呀👏🏻

本文标题:iOS像素与点

本文链接:https://www.haomeiwen.com/subject/quqkbttx.html