UIView
通过进行“图像捕获” ,您不会得到想要的结果。
当您缩放时,UIScrollView
它不会执行矢量缩放......它会执行光栅化缩放。
您可以通过将 aUILabel
用作来轻松确认这一点viewForZooming
。这是一个带有 30 磅系统字体的标签...
在1x
缩放:
在10x
缩放:
该示例的代码:
class ViewController: UIViewController, UIScrollViewDelegate {
let zoomLabel: UILabel = UILabel()
let scrollView: UIScrollView = UIScrollView()
override func viewDidLoad() {
super.viewDidLoad()
[zoomLabel, scrollView].forEach {
$0.translatesAutoresizingMaskIntoConstraints = false
}
scrollView.addSubview(zoomLabel)
view.addSubview(scrollView)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
scrollView.centerXAnchor.constraint(equalTo: g.centerXAnchor),
scrollView.centerYAnchor.constraint(equalTo: g.centerYAnchor),
scrollView.widthAnchor.constraint(equalToConstant: 300.0),
scrollView.heightAnchor.constraint(equalToConstant: 200.0),
zoomLabel.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor),
zoomLabel.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor),
zoomLabel.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor),
zoomLabel.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor),
])
zoomLabel.textColor = .red
zoomLabel.backgroundColor = .yellow
zoomLabel.font = UIFont.systemFont(ofSize: 30.0, weight: .regular)
zoomLabel.text = "Sample Text"
scrollView.delegate = self
scrollView.minimumZoomScale = 1
scrollView.maximumZoomScale = 10
view.backgroundColor = UIColor(white: 0.9, alpha: 1.0)
scrollView.backgroundColor = .white
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return zoomLabel
}
}
当您将视图内容“捕获”为UIImage
时,您将获得一个位图,该位图是视图的大小(以点x 屏幕比例为单位)。
因此,例如,在具有@2x
屏幕比例的 iPhone 8 上,300 x 200
视图将被“捕获”为UIImage
像素600 x 400
。
无论您缩放视图本身,还是视图的位图捕获,您都会得到相同的结果——缩放时边缘模糊。
您的评论包括:“......在编辑图像时......” - 这是一个常见问题,我们希望允许用户添加文本(标签)、贝塞尔路径形状、添加图像等。用户看到的例如,屏幕上可能是3000 x 2000
像素的原始图像,显示在300 x 200
点上。添加一个 30 点的标签在屏幕上可能看起来不错,但随后将其作为一个UIImage
(用于缩放或保存到磁盘),最终成为一个600 x 400
像素图像,当然,在更大的尺寸下看起来并不好。
通常,解决此问题的方法如下:
允许用户在屏幕尺寸上进行编辑,例如
- 在视图中显示
3000 x 2000
按比例缩小的像素图像300 x 200
- 添加一个贝塞尔路径,椭圆形矩形(20、20、200、200)
- 在原点添加 30 点标签
(32, 32)
然后,当“捕获”输出/缩放时
- 取原始
3000 x 2000
像素图像
- 添加一个贝塞尔路径,椭圆形矩形(20 * 10, 20 * 10, 200 * 10, 200 * 10)
- 在原点添加 (30 * 10) 点标签
(32 * 10, 32 * 10)
另一种选择是按比例缩小屏幕编辑。
因此,您可以使用300 x 200
图像视图和3000 x 2000
像素图像(缩放以适应)。当用户说“我想在 rect 中添加一个椭圆的 Bezier 路径时(20, 20, 200, 200)
,您的代码将(20 * 10, 20 * 10, 200 * 10, 200 * 10)
在图像本身的 rect 处绘制该椭圆,然后刷新.image
图像视图的属性。
这是一个更详细的示例,以帮助使事情变得清晰:
class ViewController: UIViewController, UIScrollViewDelegate {
let topView: UIView = UIView()
let topLabel: UILabel = UILabel()
let botView: UIView = UIView()
let botLabel: UILabel = UILabel()
let topScrollView: UIScrollView = UIScrollView()
let botScrollView: UIScrollView = UIScrollView()
let topStatLabel: UILabel = UILabel()
let botStatLabel: UILabel = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
[topView, topLabel, botView, botLabel, topScrollView, botScrollView, topStatLabel, botStatLabel].forEach {
$0.translatesAutoresizingMaskIntoConstraints = false
}
topView.addSubview(topLabel)
botView.addSubview(botLabel)
topScrollView.addSubview(topView)
botScrollView.addSubview(botView)
view.addSubview(topStatLabel)
view.addSubview(botStatLabel)
view.addSubview(topScrollView)
view.addSubview(botScrollView)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
topStatLabel.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
topStatLabel.leadingAnchor.constraint(equalTo: topScrollView.leadingAnchor),
topScrollView.topAnchor.constraint(equalTo: topStatLabel.bottomAnchor, constant: 4.0),
topScrollView.centerXAnchor.constraint(equalTo: g.centerXAnchor),
topScrollView.widthAnchor.constraint(equalToConstant: 300.0),
topScrollView.heightAnchor.constraint(equalToConstant: 200.0),
botScrollView.topAnchor.constraint(equalTo: topScrollView.bottomAnchor, constant: 12.0),
botScrollView.centerXAnchor.constraint(equalTo: g.centerXAnchor),
botScrollView.widthAnchor.constraint(equalToConstant: 300.0),
botScrollView.heightAnchor.constraint(equalToConstant: 200.0),
botStatLabel.topAnchor.constraint(equalTo: botScrollView.bottomAnchor, constant: 4.0),
botStatLabel.leadingAnchor.constraint(equalTo: botScrollView.leadingAnchor),
topView.widthAnchor.constraint(equalToConstant: 300.0),
topView.heightAnchor.constraint(equalToConstant: 200.0),
botView.widthAnchor.constraint(equalToConstant: 300.0 * 10.0),
botView.heightAnchor.constraint(equalToConstant: 200.0 * 10.0),
topLabel.topAnchor.constraint(equalTo: topView.topAnchor, constant: 8.0),
topLabel.leadingAnchor.constraint(equalTo: topView.leadingAnchor, constant: 8.0),
botLabel.topAnchor.constraint(equalTo: botView.topAnchor, constant: 8.0 * 10.0),
botLabel.leadingAnchor.constraint(equalTo: botView.leadingAnchor, constant: 8.0 * 10.0),
topView.topAnchor.constraint(equalTo: topScrollView.contentLayoutGuide.topAnchor),
topView.leadingAnchor.constraint(equalTo: topScrollView.contentLayoutGuide.leadingAnchor),
topView.trailingAnchor.constraint(equalTo: topScrollView.contentLayoutGuide.trailingAnchor),
topView.bottomAnchor.constraint(equalTo: topScrollView.contentLayoutGuide.bottomAnchor),
botView.topAnchor.constraint(equalTo: botScrollView.contentLayoutGuide.topAnchor),
botView.leadingAnchor.constraint(equalTo: botScrollView.contentLayoutGuide.leadingAnchor),
botView.trailingAnchor.constraint(equalTo: botScrollView.contentLayoutGuide.trailingAnchor),
botView.bottomAnchor.constraint(equalTo: botScrollView.contentLayoutGuide.bottomAnchor),
])
topLabel.textColor = .red
topLabel.backgroundColor = .yellow
topLabel.font = UIFont.systemFont(ofSize: 30.0, weight: .regular)
topLabel.text = "Sample Text"
botLabel.textColor = .red
botLabel.backgroundColor = .yellow
botLabel.font = UIFont.systemFont(ofSize: 30.0 * 10.0, weight: .regular)
botLabel.text = "Sample Text"
topScrollView.delegate = self
topScrollView.minimumZoomScale = 1
topScrollView.maximumZoomScale = 10
botScrollView.delegate = self
botScrollView.minimumZoomScale = 0.1
botScrollView.maximumZoomScale = 1
topScrollView.zoomScale = topScrollView.minimumZoomScale
botScrollView.zoomScale = botScrollView.minimumZoomScale
view.backgroundColor = UIColor(white: 0.9, alpha: 1.0)
topScrollView.backgroundColor = .white
botScrollView.backgroundColor = .white
topStatLabel.font = UIFont.systemFont(ofSize: 14, weight: .light)
topStatLabel.numberOfLines = 0
botStatLabel.font = UIFont.systemFont(ofSize: 14, weight: .light)
botStatLabel.numberOfLines = 0
let t = UITapGestureRecognizer(target: self, action: #selector(self.tapped(_:)))
view.addGestureRecognizer(t)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
updateStatLabels()
}
func updateStatLabels() -> Void {
var sTop = ""
sTop += "Label Point Size: \(topLabel.font.pointSize)"
sTop += "\n"
sTop += "Label Frame: \(topLabel.frame)"
sTop += "\n"
sTop += "View Size: \(topView.bounds.size)"
sTop += "\n"
sTop += "Zoom Scale: \(String(format: "%0.1f", topScrollView.zoomScale))"
var sBot = ""
sBot += "Zoom Scale: \(String(format: "%0.1f", botScrollView.zoomScale))"
sBot += "\n"
sBot += "View Size: \(botView.bounds.size)"
sBot += "\n"
sBot += "Label Frame: \(botLabel.frame)"
sBot += "\n"
sBot += "Label Point Size: \(botLabel.font.pointSize)"
topStatLabel.text = sTop
botStatLabel.text = sBot
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
if scrollView == topScrollView {
return topView
}
return botView
}
@objc func tapped(_ g: UITapGestureRecognizer) -> Void {
if Int(topScrollView.zoomScale) == Int(topScrollView.maximumZoomScale) {
topScrollView.zoomScale = topScrollView.minimumZoomScale
} else {
topScrollView.zoomScale += 1
}
topScrollView.contentOffset = .zero
// comparing floating point directly will fail, so round the values
if round(botScrollView.zoomScale * 10) == round(botScrollView.maximumZoomScale * 10) {
botScrollView.zoomScale = botScrollView.minimumZoomScale
} else {
botScrollView.zoomScale += 0.1
}
botScrollView.contentOffset = .zero
updateStatLabels()
}
}
顶部滚动视图有一个300 x 200
带有 30 点标签的视图,允许从1 to 10
.
底部滚动视图有一个3000 x 2000
带有 300 点标签的视图,允许从0.1 to 1.0
.
每次点击屏幕时,scrollViews 将 zoomScale 分别增加 1 和 0.1。
它在最小比例下看起来像这样:
在 5 和 0.5 级:
在 10 和 1.0 比例下: