gpt4 book ai didi

ios - 使用 Swift for iOS 绘制 UIBezierPath 随着时间推移的性能

转载 作者:搜寻专家 更新时间:2023-11-01 06:43:40 25 4
gpt4 key购买 nike

我试图了解 Swift 中的不同绘图方法以及它们为何如此执行。

下面的代码使用 UIBezierPath 绘制平滑的线条,项目可从 https://github.com/limhowe/LimSignatureView 获得

最初,当用户开始触摸屏幕时,下面代码的性能是高度响应的。然而,随着时间的推移,在屏幕上触摸和移动的时间越长,性能开始滞后,显示的绘图跟不上并且不准确(似乎遗漏了一些点)。只有在触摸屏幕结束并再次开始触摸屏幕以进行新绘图时,性能才会恢复到高度响应。


我注意到的事情:

  • self.setNeedsDisplay()被注释掉时(在override func touchesMoved),触摸屏幕时不显示绘图,但是一旦抬起手指触发override func touchesEnded,最终的结果是完美的绘制,无论持续多长时间都没有滞后或不准确的绘制点。 (这是理想情况下想要并在绘图时显示的结果。)

  • beizerPath.removeAllPoints() 被注释掉(在 override func touchesEnded 中)时,即使在用户抬起手指并开始触摸再次筛选。

  • 似乎 beizerPath.removeAllPoints() 可能会重置滞后,而 self.setNeedsDisplay() 可能会随着时间的推移导致滞后。

  • 当将 beizerPath.lineWidth 从 2 增加到更大的宽度(例如 50 或 100)时,绘图往往会略微滞后。


嗯。我很困惑为什么一切都是这样。

  • 随着时间的推移,这里到底发生了什么?

  • beizerPath.removeAllPoints()self.setNeedsDisplay()和滞后有什么关系?

  • 为什么增加 beizerPath.lineWidth 会导致一些轻微的延迟?

  • 还有什么可能导致滞后?

  • 在绘制时删除一些点是否可以提高性能?如果可以,如何实现?

  • 下面的代码需要修改什么地方才能保证完美绘制持续超时不卡顿?

感谢对代码的任何开明反馈和改进。谢谢。

//  LimSignatureView.swift
// SwiftSignatureView
//
// Created by MyAdmin on 3/6/15.
// Copyright (c) 2015 MyAdmin. All rights reserved.
//

import UIKit

class LimSignatureView: UIView {

var beizerPath: UIBezierPath = UIBezierPath()
var incrImage : UIImage?
var points : [CGPoint] = Array<CGPoint>(count: 5, repeatedValue: CGPointZero)
var control : Int = 0

var lblSignature : UILabel = UILabel()
var shapeLayer : CAShapeLayer?

required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func drawRect(rect: CGRect) {
// Drawing code
incrImage?.drawInRect(rect)
beizerPath.stroke()

// Set initial color for drawing
UIColor.redColor().setFill()
UIColor.redColor().setStroke()
beizerPath.stroke()
}

override init(frame: CGRect) {
super.init(frame: frame)

var lblHeight: CGFloat = 61.0
self.backgroundColor = UIColor.blackColor()
beizerPath.lineWidth = 2.0
lblSignature.frame = CGRectMake(0, self.frame.size.height/2 - lblHeight/2, self.frame.size.width, lblHeight);
lblSignature.font = UIFont (name: "HelveticaNeue-UltraLight", size: 30)
lblSignature.text = "Sign Here";
lblSignature.textColor = UIColor.lightGrayColor()
lblSignature.textAlignment = NSTextAlignment.Center
lblSignature.alpha = 0.3;
self.addSubview(lblSignature)
}

// MARK : - TOUCH Implementation

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
if lblSignature.superview != nil {
lblSignature.removeFromSuperview()
}

control = 0;
var touch = touches.anyObject() as UITouch
points[0] = touch.locationInView(self)

var startPoint = points[0];
var endPoint = CGPointMake(startPoint.x + 1.5, startPoint.y
+ 2);

beizerPath.moveToPoint(startPoint)
beizerPath.addLineToPoint(endPoint)
}

override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {
var touch = touches.anyObject() as UITouch
var touchPoint = touch.locationInView(self)
control++;
points[control] = touchPoint;

if (control == 4)
{
points[3] = CGPointMake((points[2].x + points[4].x)/2.0, (points[2].y + points[4].y)/2.0);
beizerPath.moveToPoint(points[0])
beizerPath.addCurveToPoint(points[3], controlPoint1: points[1], controlPoint2: points[2])

self.setNeedsDisplay()

points[0] = points[3];
points[1] = points[4];
control = 1;
}
}

override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {
self.drawBitmapImage()
self.setNeedsDisplay()

beizerPath.removeAllPoints()
control = 0
}

override func touchesCancelled(touches: NSSet!, withEvent event: UIEvent!) {
self.touchesEnded(touches, withEvent: event)
}

// MARK : LOGIC

func drawBitmapImage() {
UIGraphicsBeginImageContextWithOptions(self.bounds.size, false, 0);

if incrImage != nil {
var rectpath = UIBezierPath(rect: self.bounds)
UIColor.clearColor().setFill()
rectpath.fill()
}
incrImage?.drawAtPoint(CGPointZero)

//Set final color for drawing
UIColor.redColor().setStroke()
beizerPath.stroke()

incrImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}
}

最佳答案

它变得迟钝的原因有两个。

首先,您在触摸事件中进行绘图。这被认为不是一个好主意。我同意这是获得最干净的触摸运动跟踪的最佳方法,但如果您关心性能,那绝对不是一个好主意。

其次,您要绘制每个移动事件的整个路径(从触摸到向上)。因此,即使您在到达第四段时已经绘制了前三段,您也可以清除屏幕并再次绘制前三段。这与每次触摸事件发生的绘图相结合会导致严重的减速。

理想情况下,您会将最新的触摸事件缓存到一个对象中。然后创建一个计时器(可能是 60 fps?)并从最后一个计时器事件到当前缓存的触摸位置画一条线。这可能会导致线条无法紧密跟随触摸事件,但您可能需要尝试一下。

然后通过该优化,您应该绘制到图像上下文中,然后在需要时将该上下文绘制到屏幕上。这样,您只将最新的段绘制到上下文中,而不是重新绘制整个路径。

这两件事应该可以极大地提高您的表现。它肯定会对跟踪触摸事件的清晰度产生不利影响,但你应该能够在某处找到一个快乐的媒介。也许您缓存了所有触摸事件,然后在计时器事件上将所有最新点绘制到上下文中并将该上下文填充到屏幕上。那么您应该能够保持跟踪的清晰度并提高性能。

您还可以研究在屏幕上的 UIImageView 内绘制 UIImage。这可能会保留您的历史绘制路径,而不需要您每次都重新绘制它,但我没有这方面的经验。

关于ios - 使用 Swift for iOS 绘制 UIBezierPath 随着时间推移的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32829778/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com