在我的应用中,我正在做一些绘图,但是我做的方式效率很低,更新视图需要很长时间。我很好奇,有更好的方法可以实现这一目标。图片和代码如下。

任何帮助都将受到高度赞赏。

ios - 更好的UIBezierPath绘图iOS Swift性能?-LMLPHP

func drawDialWithCurrentValue(  currentValue:CGFloat, andNewValue newValue:CGFloat)
{
    let radius = 500.0

    let circlePath = UIBezierPath(arcCenter: CGPoint(x: 0,y: radius),
                                  radius: CGFloat(radius),
                                  startAngle: CGFloat(0),
                                  endAngle:CGFloat(M_PI * 2),
                                  clockwise: true)


    let shapeLayer = CAShapeLayer()
    shapeLayer.path = circlePath.CGPath

    shapeLayer.fillColor = UIColor.blueColor().CGColor

    shapeLayer.strokeColor = UIColor.blueColor().CGColor

    shapeLayer.lineWidth = 3.0

    drawView.layer.addSublayer(shapeLayer)

    let x0 = 0.0
    let y0 = radius

    var x1 = x0
    var y1 = y0

    var degsInRadians = 0.0

    for var index = 0; index < 360; index++
    {
        if index%2 == 0
        {
            degsInRadians = Double(index) * (M_PI/180)

            x1 = x0 + radius * cos(degsInRadians)
            y1 = y0 + radius * sin(degsInRadians)


            let linePath = UIBezierPath()

            linePath.moveToPoint(CGPoint( x: x1, y: y1))

            linePath.addLineToPoint(CGPoint( x:0, y:radius))

            let shapeLayerLine = CAShapeLayer()
            shapeLayerLine.path = linePath.CGPath

            shapeLayerLine.fillColor = UIColor.clearColor().CGColor

            shapeLayerLine.strokeColor = UIColor.greenColor().CGColor

            shapeLayerLine.lineWidth = 3.0

            drawView.layer.addSublayer(shapeLayerLine)
        }
    }

    let innerCirc = UIBezierPath(arcCenter: CGPoint(x: 0,y: radius),
        radius: CGFloat(radius - 100),
        startAngle: CGFloat(0),
        endAngle:CGFloat(M_PI * 2),
        clockwise: true)


    let shapeLayer2 = CAShapeLayer()
    shapeLayer2.path = innerCirc.CGPath

    shapeLayer2.fillColor = UIColor.blueColor().CGColor

    shapeLayer2.strokeColor = UIColor.blueColor().CGColor

    shapeLayer2.lineWidth = 3.0

    drawView.layer.addSublayer(shapeLayer2)
}

最佳答案

您只需两层即可完成此操作。一个用于线段,一个用于背景圆(其笔触颜色不同)。

此函数将为所有线段(用于顶层)创建一个BezierPath。如果您不想在每次绘制时都按比例缩放,则应设置在静态(或实例)变量中保留路径的单个副本并重用它。即使您调整形状的大小,也仅应在半径实际改变时重新计算路径。

func clockSegments(count:Int, radius:CGFloat, length:CGFloat)->UIBezierPath
{
  let allSegments = UIBezierPath()
  let baseSegment = UIBezierPath()

  // baseSegment is horizontal movement from origin, followed by line up to radius
  // (0,0).....................---------
  baseSegment.moveToPoint(    CGPointMake(radius-length, 0.0) )
  baseSegment.addLineToPoint( CGPointMake(radius,        0.0) )
  baseSegment.lineWidth = 3

  // rotate and add segments
  let segmentAngle = 2 * CGFloat(M_PI) / CGFloat(count)
  let rotate       = CGAffineTransformMakeRotation(segmentAngle)
  for _ in 1...count
  {
     allSegments.appendPath(baseSegment)
     baseSegment.applyTransform(rotate)
  }

  return allSegments
}

要获取示例中使用的参数的段路径,可以调用以下函数:
layer.path = clockSegments(360, radius:500, length:100)

在使用SpriteKit的iPad3上,渲染被分成200个段,但是如果我使用两个每个有180个的形状节点,则没有问题。这可能暗示了BezierPath中元素数量的实际限制。如果遇到此问题,则可以添加参数以偏移起始线段,并使用两个180线段图层(一个旋转1度)。

09-08 08:42