Ios 在Swift中连续绘制UIBezierPath期间消除滞后延迟
下面的代码通过覆盖接触来绘制线条,但是在连续不间断绘制的一段时间内开始出现滞后。手指在屏幕上移动的时间越长,滞后现象越严重。结果是,实际设备(CPU 98%+)上的CPU几乎达到最大值,绘图持续时间越长,生成的图像看起来就越不稳定 此外,当以极快的速度绘制时(尤其是在圆中),在Ios 在Swift中连续绘制UIBezierPath期间消除滞后延迟,ios,swift,drawing,uibezierpath,Ios,Swift,Drawing,Uibezierpath,下面的代码通过覆盖接触来绘制线条,但是在连续不间断绘制的一段时间内开始出现滞后。手指在屏幕上移动的时间越长,滞后现象越严重。结果是,实际设备(CPU 98%+)上的CPU几乎达到最大值,绘图持续时间越长,生成的图像看起来就越不稳定 此外,当以极快的速度绘制时(尤其是在圆中),在路径和临时路径(或本地路径)之间绘制的路径存在差异。虽然它们是在不同的时间绘制的,但它们似乎同时出现在屏幕上,这在视觉上分散了看到两条路径快速绘制的注意力。内部路径(路径)似乎与外部路径(临时路径)有一段距离,在下图中以红
路径
和临时路径
(或本地路径
)之间绘制的路径存在差异。虽然它们是在不同的时间绘制的,但它们似乎同时出现在屏幕上,这在视觉上分散了看到两条路径快速绘制的注意力。内部路径(路径
)似乎与外部路径(临时路径
)有一段距离,在下图中以红色突出显示
1-如何消除连续拉伸期间的滞后延迟
2-如何消除绘制路径中的差异
3-如何更改路径
和临时路径
的alpha/不透明度
class swiftView:UIView{
var strokeColor=UIColor.blueColor()
变量线宽:CGFloat=5
var快照映像:UIImage?
私有变量路径:UIBezierPath?
私有var临时路径:UIBezierPath?
私有变量点=[CGPoint]()
var对应点:Int?
必需的初始化?(编码器aDecoder:NSCoder){
super.init(编码者:aDecoder)
}
重写func drawRect(rect:CGRect){
自动释放池{
快照图像?.drawInRect(rect)
strokeColor.setStroke()
路径?.stroke()
时间路径?.stroke()
}
}
覆盖功能触摸开始(触摸:设置,withEvent事件:UIEvent?){
让触摸:AnyObject?=首先触摸
点=[触摸!.locationInView(自)]
对手得分=0
}
覆盖功能触摸移动(触摸:设置,带事件:UIEvent?){
让触摸:AnyObject?=首先触摸
让点=触摸!.locationInView(自)
点。追加(点)
设pointCount=points.count
对手得分=对手得分!+1
如果pointCount==2{
临时路径=createPathStartingAtPoint(点[0])
临时路径?.addLineToPoint(点[1])
setNeedsDisplay()
}如果pointCount==3,则为else{
临时路径=createPathStartingAtPoint(点[0])
时间路径?.addQuadCurveToPoint(点[2],控制点:点[1])
setNeedsDisplay()
}如果pointCount==4,则为else{
临时路径=createPathStartingAtPoint(点[0])
temporaryPath?.addCurveToPoint(点[3],控制点1:点[1],控制点2:点[2])
//setNeedsDisplay()
如果对方得分低于50分{
self.setNeedsDisplay()
}否则{
时间路径=零
self.constructionIncrementalImage()
路径=零
self.setNeedsDisplay()
对手得分=0
}
}如果pointCount==5,则为else{
点[3]=CGPointMake((点[2].x+点[4].x)/2.0,(点[2].y+点[4].y)/2.0)
//创建一个四次bezier,直到第4点
如果分数[4]!=分数[3]{
设长度=hypot(点[4]。x-点[3]。x,点[4]。y-点[3]。y)/2.0
设角度=atan2(点[3]。y-点[2]。y,点[4]。x-点[3]。x)
设controlPoint=CGPoint(x:points[3]。x+cos(angle)*长度,y:points[3]。y+sin(angle)*长度)
临时路径=createPathStartingAtPoint(点[3])
临时路径?.addQuadCurveToPoint(点[4],控制点:控制点)
}否则{
时间路径=零
}
如果路径==nil{
路径=createPathStartingAtPoint(点[0])
}
路径?.addCurveToPoint(点[3],控制点1:点[1],控制点2:点[2])
self.setNeedsDisplay()
点数=[点数[3],点数[4]]
}
}
覆盖func touchesEnded(触摸:设置,withEvent事件:UIEvent?){
self.constructionIncrementalImage()
路径=零
self.setNeedsDisplay()
对手得分=0
}
覆盖功能触摸已取消(触摸:设置?,带事件:UIEvent?){
self.touchesend(touchs!,with event:event)
}
私有函数createPathStartingAtPoint(点:CGPoint)->UIBezierPath{
让localPath=UIBezierPath()
localPath.moveToPoint(点)
localPath.lineWidth=线宽
localPath.lineCapStyle=.Round
localPath.lineJoinStyle=.Round
返回本地路径
}
private func constructionIncrementalImage(){
UIGraphicsBeginImageContextWithOptions(self.bounds.size,false,0.0)
strokeColor.setStroke()
快照图像?.drawAtPoint(CGPointZero)
路径?.stroke()
时间路径?.stroke()
snapshotImage=UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsSendImageContext()
}
}
您问:
class swiftView: UIView {
var strokeColor = UIColor.blueColor()
var lineWidth: CGFloat = 5
var snapshotImage: UIImage?
private var path: UIBezierPath?
private var temporaryPath: UIBezierPath?
private var points = [CGPoint]()
var counterPoints:Int?
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func drawRect(rect: CGRect) {
autoreleasepool {
snapshotImage?.drawInRect(rect)
strokeColor.setStroke()
path?.stroke()
temporaryPath?.stroke()
}
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch: AnyObject? = touches.first
points = [touch!.locationInView(self)]
counterPoints = 0
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch: AnyObject? = touches.first
let point = touch!.locationInView(self)
points.append(point)
let pointCount = points.count
counterPoints = counterPoints! + 1
if pointCount == 2 {
temporaryPath = createPathStartingAtPoint(points[0])
temporaryPath?.addLineToPoint(points[1])
setNeedsDisplay()
} else if pointCount == 3 {
temporaryPath = createPathStartingAtPoint(points[0])
temporaryPath?.addQuadCurveToPoint(points[2], controlPoint: points[1])
setNeedsDisplay()
} else if pointCount == 4 {
temporaryPath = createPathStartingAtPoint(points[0])
temporaryPath?.addCurveToPoint(points[3], controlPoint1: points[1], controlPoint2: points[2])
// setNeedsDisplay()
if counterPoints! < 50 {
self.setNeedsDisplay()
} else {
temporaryPath = nil
self.constructIncrementalImage()
path = nil
self.setNeedsDisplay()
counterPoints = 0
}
} else if pointCount == 5 {
points[3] = CGPointMake((points[2].x + points[4].x)/2.0, (points[2].y + points[4].y)/2.0)
// create a quad bezier up to point 4, too
if points[4] != points[3] {
let length = hypot(points[4].x - points[3].x, points[4].y - points[3].y) / 2.0
let angle = atan2(points[3].y - points[2].y, points[4].x - points[3].x)
let controlPoint = CGPoint(x: points[3].x + cos(angle) * length, y: points[3].y + sin(angle) * length)
temporaryPath = createPathStartingAtPoint(points[3])
temporaryPath?.addQuadCurveToPoint(points[4], controlPoint: controlPoint)
} else {
temporaryPath = nil
}
if path == nil {
path = createPathStartingAtPoint(points[0])
}
path?.addCurveToPoint(points[3], controlPoint1: points[1], controlPoint2: points[2])
self.setNeedsDisplay()
points = [points[3], points[4]]
}
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
self.constructIncrementalImage()
path = nil
self.setNeedsDisplay()
counterPoints = 0
}
override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {
self.touchesEnded(touches!, withEvent: event)
}
private func createPathStartingAtPoint(point: CGPoint) -> UIBezierPath {
let localPath = UIBezierPath()
localPath.moveToPoint(point)
localPath.lineWidth = lineWidth
localPath.lineCapStyle = .Round
localPath.lineJoinStyle = .Round
return localPath
}
private func constructIncrementalImage() {
UIGraphicsBeginImageContextWithOptions(self.bounds.size, false, 0.0)
strokeColor.setStroke()
snapshotImage?.drawAtPoint(CGPointZero)
path?.stroke()
temporaryPath?.stroke()
snapshotImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}
}
class SmoothCurvedLinesView: UIView {
var strokeColor = UIColor.blueColor()
var lineWidth: CGFloat = 20
var snapshotImage: UIImage?
private var path: UIBezierPath?
private var temporaryPath: UIBezierPath?
private var points = [CGPoint]()
private var totalPointCount = 0
override func drawRect(rect: CGRect) {
snapshotImage?.drawInRect(rect)
strokeColor.setStroke()
path?.stroke()
temporaryPath?.stroke()
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch: AnyObject? = touches.first
points = [touch!.locationInView(self)]
totalPointCount = totalPointCount + 1
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch: AnyObject? = touches.first
let point = touch!.locationInView(self)
points.append(point)
totalPointCount = totalPointCount + 1
updatePaths()
if totalPointCount > 50 {
constructIncrementalImage(includeTemporaryPath: false)
path = nil
totalPointCount = 0
}
setNeedsDisplay()
}
private func updatePaths() {
// update main path
while points.count > 4 {
points[3] = CGPointMake((points[2].x + points[4].x)/2.0, (points[2].y + points[4].y)/2.0)
if path == nil {
path = createPathStartingAtPoint(points[0])
}
path?.addCurveToPoint(points[3], controlPoint1: points[1], controlPoint2: points[2])
points.removeFirst(3)
}
// build temporary path up to last touch point
let pointCount = points.count
if pointCount == 2 {
temporaryPath = createPathStartingAtPoint(points[0])
temporaryPath?.addLineToPoint(points[1])
} else if pointCount == 3 {
temporaryPath = createPathStartingAtPoint(points[0])
temporaryPath?.addQuadCurveToPoint(points[2], controlPoint: points[1])
} else if pointCount == 4 {
temporaryPath = createPathStartingAtPoint(points[0])
temporaryPath?.addCurveToPoint(points[3], controlPoint1: points[1], controlPoint2: points[2])
}
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
constructIncrementalImage()
path = nil
temporaryPath = nil
setNeedsDisplay()
}
override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {
touchesEnded(touches!, withEvent: event)
}
private func createPathStartingAtPoint(point: CGPoint) -> UIBezierPath {
let localPath = UIBezierPath()
localPath.moveToPoint(point)
localPath.lineWidth = lineWidth
localPath.lineCapStyle = .Round
localPath.lineJoinStyle = .Round
return localPath
}
private func constructIncrementalImage(includeTemporaryPath includeTemporaryPath: Bool = true) {
UIGraphicsBeginImageContextWithOptions(bounds.size, false, 0.0)
strokeColor.setStroke()
snapshotImage?.drawAtPoint(CGPointZero)
path?.stroke()
if (includeTemporaryPath) { temporaryPath?.stroke() }
snapshotImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}
}
override func drawRect(rect: CGRect) {
snapshotImage?.drawInRect(rect)
strokeColor.setStroke()
path?.stroke()
strokeColor.colorWithAlphaComponent(0.5).setStroke()
temporaryPath?.stroke()
}