I have a chart which is in the shape of an gauge which has multiple design elements to it (see attachment). Key parts I'm struggling with is really getting a decent arc shape with dashed lines.
So far I'm not sure if I should be going down Core Graphics route or using something within UIKit, i.e. UIBezierPath.
I've tried this within a class that extend UIView which gives me the dashed lines but the arc itself isn't quite good enough:
class Example: UIView {
    override func drawRect(rect: CGRect) {
        let context = UIGraphicsGetCurrentContext()
        CGContextSetLineWidth(context, 10.0)
        CGContextSetStrokeColorWithColor(context, UIColor.greenColor().CGColor)
        let dashArray:[CGFloat] = [1,10, 0, 0]
        CGContextSetLineDash(context, 2, dashArray, 4)
        CGContextMoveToPoint(context, 10, 200)
        CGContextAddQuadCurveToPoint(context, 0, 0, 100, 200)
        CGContextStrokePath(context)
    }
}
There are then some other ways to get this going using UIBezierPath but I'm not sure how I would go about applying the dashed lines through here...
The main base of getting the arc with dashed lines is my main goal atm - I'm sure once I get this I'll be able to workout the gradient and animation :)
Any help would be appreciated :)

What you need is two bezier paths with different dash widths.
You can start from herE:
T0 get the higher dash bezier:

UIBezierPath* oval2Path = [UIBezierPath bezierPathWithOvalInRect: yourRect];
[UIColor.redColor setStroke];
oval2Path.lineWidth = 13;
CGFloat oval2Pattern[] = {2, 20};
[oval2Path setLineDash: oval2Pattern count: 2 phase: 0];
[oval2Path stroke];
and to get small dash patterned bezier, you need to reduce the gap between dashes:

UIBezierPath* ovalPath = [UIBezierPath bezierPathWithOvalInRect: yourRect];
[UIColor.redColor setStroke];
ovalPath.lineWidth = 6;
CGFloat ovalPattern[] = {2, 1};   
[ovalPath setLineDash: ovalPattern count: 2 phase: 0];
[ovalPath stroke];
and now you can put these two bezier path together:

- (void)drawFrame: (CGRect)frame
{
    // Oval Drawing
    UIBezierPath* ovalPath = [UIBezierPath bezierPathWithOvalInRect: CGRectMake(CGRectGetMinX(frame), CGRectGetMinY(frame), 70, 70)];
    [UIColor.redColor setStroke];
    ovalPath.lineWidth = 6;
    CGFloat ovalPattern[] = {2, 1};
    [ovalPath setLineDash: ovalPattern count: 2 phase: 0];
    [ovalPath stroke];
    // Oval 2 Drawing
    UIBezierPath* oval2Path = [UIBezierPath bezierPathWithOvalInRect: CGRectMake(CGRectGetMinX(frame) + 0.5, CGRectGetMinY(frame) - 0.5, 70, 70)];
    [UIColor.redColor setStroke];
    oval2Path.lineWidth = 13;
    CGFloat oval2Pattern[] = {2, 20};
    [oval2Path setLineDash: oval2Pattern count: 2 phase: 0];
    [oval2Path stroke];
}
Swift:
func drawCanvas1(frame frame: CGRect = CGRect(x: 86, y: 26, width: 70, height: 70)) {
    let context = UIGraphicsGetCurrentContext()
    // Oval Drawing
    let ovalPath = UIBezierPath(ovalInRect: CGRect(x: frame.minX, y: frame.minY, width: 70, height: 70))
    UIColor.redColor().setStroke()
    ovalPath.lineWidth = 6
    CGContextSaveGState(context)
    CGContextSetLineDash(context, 4.5, [0, 1], 2)
    ovalPath.stroke()
    CGContextRestoreGState(context)
    // Oval 2 Drawing
    let oval2Path = UIBezierPath(ovalInRect: CGRect(x: frame.minX + 0.5, y: frame.minY - 0.5, width: 70, height: 70))
    UIColor.redColor().setStroke()
    oval2Path.lineWidth = 13
    CGContextSaveGState(context)
    CGContextSetLineDash(context, 39, [1, 10], 2)
    oval2Path.stroke()
    CGContextRestoreGState(context)
}
Similarly you can follow the same approach for arcs, where you just need to replace the bezierPathWithOval method with bezierPathWithArcCenter method
Please note that:
CGFloat ovalPattern[] = {2, 1};   //2 is Dash width and 1 is gap between dashes
You can adjust these values for accuracy!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With