如何使用swift中的bézier路径创建不同大小的图形馅饼?

时间:2015-03-28 17:35:52

标签: ios swift uibezierpath graphic quartz-core

我想用8个相等的切片制作一个漂亮的图形饼,可以根据Int或类似的东西单独缩放或调整大小。这看起来就像下面的所有切片应该同样切割:

enter image description here

我在Objective-C中尝试了这个,但只做了一个片段:

  -(CAShapeLayer *)createPieSlice {
    CAShapeLayer *slice = [CAShapeLayer layer];
    slice.fillColor = [UIColor redColor].CGColor;
    slice.strokeColor = [UIColor blackColor].CGColor;
    slice.lineWidth = 3.0;

    CGFloat angle = DEG2RAD(-60.0);
    CGPoint center = CGPointMake(100.0, 100.0);
    CGFloat radius = 100.0;

    UIBezierPath *piePath = [UIBezierPath bezierPath];
    [piePath moveToPoint:center];

    [piePath addLineToPoint:CGPointMake(center.x + radius * cosf(angle), center.y + radius * sinf(angle))];

    [piePath addArcWithCenter:center radius:radius startAngle:angle endAngle:DEG2RAD(60.0) clockwise:YES];

    //  [piePath addLineToPoint:center];
    [piePath closePath]; // this will automatically add a straight line to the center
    slice.path = piePath.CGPath;

    return slice;
    }

如何在swift中实现该图形?

2 个答案:

答案 0 :(得分:4)

将问题分解为逻辑部分。

你有不同弧宽的楔形。所有这些半径需要加起来一整圈。我认为它们代表了加起来达到100%的某些部分。你想要特定的订单吗?如果是这样,请按照您想要的顺序映射您的分数,这样它们总计可以达到100%。

然后编写以零角度开始的代码,并创建指定分数为2π的弧。每一个都将从前一个结束开始。根据您需要的数据指定适当的半径。

现在编写在UIBezierPath中创建封闭路径段的代码。

修改

你已经澄清了,并且告诉我们你总是想要8个宽度相同但半径不同的切片。

因此,您需要编写需要8个输入值的代码,并将其绘制为具有不同半径值的8个弧。

假设你的输入值是一个从0到1的浮点数组。在零时,楔形是零大小的。在1.0处,它是适合您视图的最大圆形大小(方形视图宽度的一半。

所以你要创建一个包含8个浮点数的数组:

var fractions = [0.5, 0.7, 0.3, 0.1, 1.0 .6, .2, .9]

创建具有8个弧的贝塞尔曲线的代码可能如下所示:

let pi = 3.1415826
let largestRadius = myView.width/2

let piePath = UIBezierPath()
for (index, afloat) in fractions
{
  let startAngle = Double(index) / fractions.count * 2 * pi
  let endAngle = Double(index+1) / fractions.count * 2 * pi
  let thisRadius = largestRadius * afloat
  let center = CGPointMake( myView.width/2, myView.height/2)
  piePath.moveToPoint(center)

  piePath.addArcWithCenter(center,
    radius: thisRadius,
    startAngle: startAngle,
    endAngle: endAngle,
    clockwise: true)
  piePath.lineToPoint(center)
  piePath.closePath()
}

认为上面的代码会创建8个封闭的切片路径,但我并不积极。可能需要在第一个moveToPoint调用和弧调用之间添加lineToPoint调用。

编辑#2:

由于我正在学习Swift,我决定将其作为练习,并编写了一个示例项目,该项目使用形状图层和从UIBezierPath创建的自定义路径生成饼图,如上所述。您可以在github上找到示例项目:PieCharts project on Github

答案 1 :(得分:1)

我已经设法使用Core Graphics解决了我的问题!感谢@ duncan-c感兴趣。

修改 我放弃了第一个有利于@duncan-c解决方案的解决方案,这对我的需求更有效!

import UIKit

class Pie: UIView {

     // In range of 0.0 to 1.0
    var endArc:CGFloat = 0.0 {
    didSet {
        setNeedsDisplay()
    }
}

var arcWidth:CGFloat = 5.0
var arcColor = UIColor()
var arcBackgroundColor = UIColor.clearColor()
var arcStrokeColor = UIColor()
var startFloat:CGFloat = 0.0
var radius:CGFloat = 0.0
var radiusSize: CGFloat = 0.0

override func drawRect(rect: CGRect) {

    // Important constants for circle
    let fullCircle = 2.0 * CGFloat(M_PI)
    let start:CGFloat = startFloat * fullCircle
    let end:CGFloat = endArc * fullCircle + start

    // Find the centerpoint of the rect
    var centerPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect))

    // Set the radius
    radius = (radiusSize - arcWidth) / 2.0

    // Starting point for all drawing code is getting the context.
    let context = UIGraphicsGetCurrentContext()

    // Set colorspace
    let colorspace = CGColorSpaceCreateDeviceRGB()

    // Set line attributes
    CGContextSetLineWidth(context, arcWidth)

    // Draw the pie
    CGContextSetStrokeColorWithColor(context, arcStrokeColor.CGColor)
    CGContextSetFillColorWithColor(context, arcColor.CGColor)
    CGContextMoveToPoint(context, centerPoint.x, centerPoint.y)
    CGContextAddArc(context, centerPoint.x, centerPoint.y, radius, start, end, 0)
    CGContextFillPath(context)
}
}

然后将UIView子类化为我需要使用的地方:

    @IBOutlet weak var graph: Pie!

override func awakeFromNib() {
    super.awakeFromNib()

    let backgroundTrackColor = UIColor.clearColor()
    let strokeColor = UIColor(white: 0.15, alpha: 1.0)

    graph.radiusSize = 50.0
    graph.arcBackgroundColor = backgroundTrackColor
    graph.arcStrokeColor = strokeColor
    graph.arcColor = UIColor.redColor()
    graph.startFloat = 0.750
    graph.arcWidth = 5.0
    graph.endArc = 0.125
}