iOS绘制1像素的线

news/2024/11/9 0:49:39/

有时候页面上需要绘制1像素的分隔线,可以通过添加 view 的方式,也可以通过 UIGraphicsGetCurrentContext 的方式实现。但是通过UIGraphicsGetCurrentContext实现的时候需要注意像素的问题。

在绘制1像素线之前,我们先来看一下绘制高度为50的线是什么样的效果。以下图均为模拟器上的截图放大后显示,红色为view的方式,黑色为UIGraphicsGetCurrentContext的方式,分别在2倍屏和3倍屏的效果。

let line1 = UIView(frame: CGRect(x: 0, y: 50, width: 100, height: 50))
line1.backgroundColor = .red
addSubview(line1)
paint.setLineWidth(50)
paint.move(to: CGPoint(x: 100, y: 50))
paint.addLine(to: CGPoint(x: 200, y: 50))
paint.setStrokeColor(red: 0, green: 0, blue: 0, alpha: 1)
paint.strokePath()

iPhone Xʀ: iPhone Xs Max: 

从图中可以看出,paint.strokePath() 这个方式是居中绘制。

下面再看下绘制1像素的效果。

let line1 = UIView(frame: CGRect(x: 0, y: 1, width: 100, height: 1/UIScreen.main.scale))paint.setLineWidth(1/UIScreen.main.scale)

iPhone Xʀ: iPhone Xs Max:

由上看出,通过View的方式没有问题,通过paint绘制的会“失真”,出现两个像素的灰线。苹果官方的解释翻译后是:奇数像素宽度的线在渲染的时候将会表现为柔和的宽度扩展到向上的整数宽度的线,除非你手动的调整线的位置,使线刚好落在一行或列的显示单元内。

可以这么理解:苹果在绘制的时候,最低绘制单位为1个单元。由于paint是居中绘制,绘制1像素时,坐标相邻的两个单元内各占0.5像素,此时跨越两个单元,由于最低绘制为1个单元,所以绘制出了两个像素。如下图所示:

此图显示的是一条竖线。

如何解决呢?苹果给出的方案是设置偏移量,使绘制的1像素线在1个单元内。

我们可以这么处理,以paint绘制横线为例,使绘制的中心位置往下偏移0.5像素,这样中心位置就落在1个单元的中间位置,居中绘制时,上下各占0.5像素,此时正好占据1个单元,所以绘制的效果也正好是1像素。达到了和UIView的方式一样的效果。

0.5像素为 (1/UIScreen.main.scale/2)

let line1 = UIView(frame: CGRect(x: 0, y: 1, width: 100, height: 1/UIScreen.main.scale))
line1.backgroundColor = .red
addSubview(line1)
paint.setLineWidth(1/UIScreen.main.scale)
paint.move(to: CGPoint(x: 100, y: 1+(1/UIScreen.main.scale/2)))
paint.addLine(to: CGPoint(x: 200, y: 1+(1/UIScreen.main.scale/2)))
paint.setStrokeColor(red: 0, green: 0, blue: 0, alpha: 1)
paint.strokePath()

iPhone Xʀ: iPhone Xs Max:

接下来的任务就是把 (1/UIScreen.main.scale/2) 设置为一个常量,添加一个公用的方法,以便项目中使用就好了。


http://www.ppmy.cn/news/833531.html

相关文章

关于前端开发像素的一些记录

像素 屏幕就是由一个一个发光的小点构成的,这一个个的小点就是像素,在前端开发中,像素主要分成两种情况,CSS像素和物理像素 物理像素:上述说的小点点就是物理像素CSS像素:前端开发中,使用的都…

苹果页面设计规范吐血整理

苹果567(775乘1334px) 主流设计尺寸 一般设计以这个为标准 如果要转为三倍图 乘以1.5等比例缩放形成自适应 1.界面设计包括布局层,图文排版层,图标层。 2. iPhone界面布局讲究8px原则。所有间距和标准尺寸都是应该是8px的倍数。如iPhone678的状态栏40px,导航栏88px,标签栏…

leetcode每日一题——238.除自身以外数组的乘积(面试经典150题)

一、题目描述与要求 238. 除自身以外数组的乘积 - 力扣(LeetCode) 题目描述 给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素…

【设计模式】23种设计模式——单例模式(原理讲解+应用场景介绍+案例介绍+Java代码实现)

单例模式(Singleton) 介绍 所谓类的单例设计模式,就是采取一定的方法,保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)。比如Hibernate的Sessio…

cudaGetDeviceCount returned 999

安装nvidia GPU卡驱动后, 运行nvidia-smi 输出正常。 安装CUDA,编译运行例子deviceQuery,输出 CUDA Device Query (Runtime API) version (CUDART static linking) cudaGetDeviceCount returned 999 -> unknown error Result FAIL …

money显示格式999,999,999

DECLARE mny moneySET mny 123456.16SELECT SUBSTRING(convert(varchar,cast(mny as money),1),0,CHARINDEX(.,convert(varchar,cast(mny as money),1)) ) as MONEY

to_char(数据,'FM999,999,999,999,990.00')

select to_char(0.596,‘FM999,999,999,990.00’) from dual   它的执行结果如下:   怎样使查出来类似0.60的小数带0,答案是:使用如上的格式即可。   ①其9代表:如果存在数字则显示数字,不存在则显示空格。   …