如何每1/10秒有效地绘制线条

时间:2017-08-01 14:41:55

标签: ios swift animation drawing

我有一个缓冲区,每1/10秒就会填充一个浮点数据点。当数据准备就绪(每次大约4000个)时,我将该数据转换为行。

我在这里的问题,正如您可能已经知道的那样,绘图变得非常慢。我在下面发布了一些代码。

这是我的自定义UIView。这个方法被调用一次。

override func layoutSubviews() {
    super.layoutSubviews()

    // init stuff for drawing animation
    path = UIBezierPath()
    yOff = Float(self.bounds.height / 2)
    lastPoint = CGPoint(x: 1.0, y: Double(yOff))
    path.move(to: lastPoint)
    path.addLine(to: lastPoint)

    pathLayer = CAShapeLayer()
    pathLayer.frame = CGRect(x: 0, y: 0, width: self.bounds.width, height: self.bounds.height)
    pathLayer.path = path.cgPath
    pathLayer.strokeColor = UIColor.red.cgColor
    pathLayer.fillColor = nil
    pathLayer.lineWidth = 0.2
    pathLayer.lineJoin = kCALineJoinBevel


    let pathAnimation: CABasicAnimation = CABasicAnimation(keyPath: "strokeEnd")
    pathAnimation.duration = 0.1
    pathAnimation.fromValue = NSNumber(value: 0.0)
    pathAnimation.toValue = NSNumber(value:1.0)


    self.layer.addSublayer(pathLayer)


    pathLayer.add(pathAnimation, forKey: "strokeEnd")
}

以下方法执行实际绘图,由" setNeedsDisplay"每1/10秒。

override func draw(_ rect: CGRect) {

    // this is where the magic (animation) happens
    CATransaction.begin()
    pathLayer.path = path.cgPath
    CATransaction.commit()

}

这是在viewcontroller中。我循环遍历数据点,为每个数据创建一个CGPoint。可能效率低下;欢迎任何帮助/想法:

for _s in samples
{
    let currP = CGPoint(x: cX * xModifier, y: yOffSet + (CGFloat(_s)*yModifier))
    cX += xLen
    self.waveView.path.addLine(to: currP)
    ctr = ctr + 1
}

DispatchQueue.main.async {
    self.waveView.setNeedsDisplay()
}

提前致谢。

1 个答案:

答案 0 :(得分:1)

有几点想法:

  1. 请勿更新draw中的图层。您应该完全消除该方法,因为它只在您抚摸自己的路径时使用。但是你正在使用CAShapeLayer,这就不需要做任何事了。更新路径后,请将对setNeedsDisplay的呼叫替换为仅直接更新pathLayer.path的代码。如果你想要制作动画,那么也可以在这里CABasicAnimation执行。

  2. 与您当前的问题无关,您应该注意在layoutSubviews中添加图层。该方法可以被多次调用。也许你现在只看到一次叫它,但可以反复调用它。例如,如果您旋转设备,它可以被调用。如果您使用autolayout,并执行触发autolayout引擎的操作,则可以调用它。作为一般规则,它可以被多次调用(即使你现在只看到它只调用一次)。

  3. 向路径添加4000个线段非常多,渲染速度很慢。从您的问题来看,您添加另外4000个线段的频率并不完全清楚。

    通常当我们想要添加到现有(可能很长)的贝塞尔曲线路径时,我们会拍摄现有视图的快照,在UIImageView中渲染,然后只渲染路径的增量部分CAShapeLayer。这确保了一致的性能模式,只是渲染图像和增量部分的时间,而不是尝试重新渲染越来越长的UIBezierPath