我目前正在制作绘图应用。我正在为iOS构建它,并且正在使用Swift 3这样做。
这只是一个基本的绘图应用程序,但我正在尝试添加一个额外的功能。我从一个UIScrollView开始,然后在该滚动视图中添加了一个图像视图。所有绘图部分都是使用图像视图完成的。首次启动应用程序时,滚动视图会完全放大。当您切换到“缩放模式”时,可以捏合缩放。问题是,当您第一次打开应用程序时,在放大时绘制时,绘图非常模糊。为了解决这个问题,我可以使用一行代码:
UIGraphicsBeginImageContextWithOptions((self.view.frame.size), false, 7.0)
这会导致绘图在放大时看起来很棒,但会导致应用程序运行非常迟缓。令我困惑的是,如果我将上面的代码更改为:
UIGraphicsBeginImageContextWithOptions((self.view.frame.size), false, 0.0)
并且一直缩小,绘图看起来完全一样(授予,我一直缩放)但它不再是滞后的。我知道这可能不是非常清楚,所以这是一个视频,显示第一个场景中发生的事情:https://youtu.be/E_9FKf1pUTY和第二个场景:https://youtu.be/OofFTS4Q0OA
所以基本上,我想知道是否有办法将放大的区域视为自己的视图。在我看来,好像应用程序正在更新整个图像视图,而不仅仅是在任何给定时间可见的部分。有没有办法只更新绘制的图像视图部分?对不起,如果这是一个令人困惑的帖子,如果有任何你不明白的事情,请随时提问。为了清楚起见,我将包括下面的所有绘图代码:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
print("Touches began")
swiped = true
if let touch = touches.first {
lastPoint = touch.location(in: scrollView)
lastPoint.x = lastPoint.x / scrollView.zoomScale
lastPoint.y = lastPoint.y / scrollView.zoomScale
}
}
func drawLines(fromPoint:CGPoint,toPoint:CGPoint) {
print("\(fromPoint.x), \(fromPoint.y)")
//UIGraphicsBeginImageContext(self.view.frame.size)
UIGraphicsBeginImageContextWithOptions((scrollView.frame.size), false, 0.0)
imageView.image?.draw(in: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))
let context = UIGraphicsGetCurrentContext()
context?.move(to: CGPoint(x: fromPoint.x, y: fromPoint.y))
context?.addLine(to: CGPoint(x: toPoint.x, y: toPoint.y))
context?.setBlendMode(CGBlendMode.normal)
context?.setLineCap(CGLineCap.round)
if erase == true {
context?.setLineWidth(30)
}
if erase == false {
context?.setLineWidth(CGFloat(sizeVar))
}
if color == "black" {
context?.setStrokeColor(UIColor.black.cgColor)
}
if color == "white" {
context?.setStrokeColor(UIColor.white.cgColor)
}
if color == "blue" {
context?.setStrokeColor(UIColor.blue.cgColor)
}
if color == "cyan" {
context?.setStrokeColor(UIColor.cyan.cgColor)
}
if color == "green" {
context?.setStrokeColor(UIColor.green.cgColor)
}
if color == "magenta" {
context?.setStrokeColor(UIColor.magenta.cgColor)
}
if color == "red" {
context?.setStrokeColor(UIColor.red.cgColor)
}
if color == "yellow" {
context?.setStrokeColor(UIColor.yellow.cgColor)
}
context?.strokePath()
imageView.image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
swiped = true
if let touch = touches.first {
var currentPoint = touch.location(in: scrollView)
currentPoint.x = currentPoint.x / scrollView.zoomScale
currentPoint.y = currentPoint.y / scrollView.zoomScale
drawLines(fromPoint: lastPoint, toPoint: currentPoint)
lastPoint = currentPoint
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if !swiped {
drawLines(fromPoint: lastPoint, toPoint: lastPoint)
}
}
答案 0 :(得分:0)
函数UIGraphicsBeginImageContextWithOptions(_:_:_:)
中的scale参数不是质量设置,您不应该在其中放置任意值。这是一个比例因子,它类似于图像的@ 1x,@ 2x和@ 3x设置。它告诉系统在将图像像素映射到屏幕像素时使用的缩放因子。在大多数(几乎所有)情况下,你应该使用0,这意味着“使用屏幕的原生尺度”(@ 2x用于正常视网膜,或@ 3x用于iPhone 6+和7+。)你永远不应该将它设置为任意像7这样的值创建一个像往常一样7倍像素的图像,并强制系统每次都缩放它以进行画面绘制,这需要更多时间并且速度更慢。
接下来,为每个新行创建一个新图像是一种非常低效的绘图方式。它不断创建和释放大块内存,然后每次都必须完全重绘屏幕。相反,我会设置一个视图,它有一个CAShapeLayer
作为它的支持层,并更新层中安装的路径。