如何在Mac的Swift中实现NSView内元素的精准英寸级绘制?
解决MacBook Pro屏幕上精准绘制1英寸间距的问题
问题根源
你之前用72 * backingScaleFactor = 144作为间距的计算逻辑错误,因为72pt=1英寸是印刷行业的DPI标准,和屏幕的物理像素密度(PPI)无关。backingScaleFactor只是逻辑点到后备存储像素的转换比例,但逻辑点本身的物理尺寸由屏幕的实际物理大小和系统设置的逻辑分辨率决定,不是固定的1/72英寸。
正确计算方式
要实现文档1英寸内容对应屏幕1物理英寸,需要基于屏幕的实际物理尺寸和逻辑分辨率来计算每英寸对应的逻辑点数量:
- 获取屏幕的物理宽度(转换为英寸,系统返回的
physicalSize单位是毫米) - 获取屏幕的逻辑宽度(系统设置的分辨率,单位是点)
- 计算1物理英寸对应的逻辑点数量
代码实现
guard let mainScreen = NSScreen.main else { // 处理无可用屏幕的异常情况 return } // 将屏幕物理宽度从毫米转换为英寸 let physicalWidthInInches = mainScreen.physicalSize.width / 25.4 // 获取屏幕的逻辑宽度(系统缩放后的分辨率,单位:点) let logicalScreenWidth = mainScreen.frame.width // 计算1物理英寸对应的逻辑点数量 let pointsPerPhysicalInch = logicalScreenWidth / physicalWidthInInches // 示例:绘制间距为1英寸的"A"和"B" let pointA = CGPoint(x: 500, y: 100) let pointB = CGPoint(x: pointA.x + pointsPerPhysicalInch, y: pointA.y) "A".draw(at: pointA, withAttributes: nil) "B".draw(at: pointB, withAttributes: nil)
注意事项
- 该计算会自动适配系统的显示器缩放设置(比如"更多空间"或"默认"模式),因为
mainScreen.frame.width会随缩放变化 - 确保绘制所在的NSView没有额外的
transform变换,否则会偏移实际绘制位置 - macOS坐标系默认原点在左下角,绘制时注意y轴方向和预期一致
内容的提问来源于stack exchange,提问作者David Rector
相关产品推荐
相关产品推荐

