Swift draw alternating dashed and dotted line with UIBezierPath - ios

I'm attempting to draw a line with a UIBezierPath that alternates between dots and dashes. Here's my code so far:
func drawAlternatingDashesAndDots() {
let path = UIBezierPath()
path.move(to: CGPoint(x: 10,y: 10))
path.addLine(to: CGPoint(x: 290,y: 10))
path.lineWidth = 8
let dots: [CGFloat] = [0.001, path.lineWidth * 2]
path.setLineDash(dots, count: dots.count, phase: 0)
for i in 0...10 {
if i % 2 == 0 {
// Even Number
path.lineCapStyle = CGLineCap.round
} else {
// Odd Number
path.lineCapStyle = CGLineCap.square
}
}
UIGraphicsBeginImageContextWithOptions(CGSize(width:300, height:20), false, 2)
UIColor.white.setFill()
UIGraphicsGetCurrentContext()!.fill(.infinite)
UIColor.black.setStroke()
path.stroke()
let image = UIGraphicsGetImageFromCurrentImageContext()
dashDotDashLineView.image = image
UIGraphicsEndImageContext()
}
However, in my image view, only dots are rendered:
I'm probably misunderstanding something about how UIBezierPath works; any help appreciated!

The UIBezierPath documentation explains the meaning of the pattern argument:
A C-style array of floating point values that contains the lengths (measured in points) of the line segments and gaps in the pattern. The values in the array alternate, starting with the first line segment length, followed by the first gap length, followed by the second line segment length, and so on.
In your code, 0.001 is the first value in the pattern, so it is a line segment length, and is small enough to be drawn as a dot. The second value in the pattern is path.lineWidth * 2, so it is a gap length, which is the distance between the dots.
If you want to alternate dots and dashes, you have to pass a pattern containing four numbers: a line segment length, a gap, another line segment length, and another gap.
let dots: [CGFloat] = [
0.001, // dot
path.lineWidth * 2, // gap
path.lineWidth * 2, // dash
path.lineWidth * 2, // gap
]

Related

Animating CAShapeLayer path smoothly

I'm trying to make a Gauge UIView to mimic the following image as close as possible
func gradientBezierPath(percent: CGFloat) -> UIBezierPath {
// vary this to move the start of the arc
let startAngle = CGFloat(180).toRadians()//-CGFloat.pi / 2 // This corresponds to 12 0'clock
// vary this to vary the size of the segment, in per cent
let proportion = CGFloat(50 * percent)
let centre = CGPoint (x: self.frame.size.width / 2, y: self.frame.size.height / 2)
let radius = self.frame.size.height/4//self.frame.size.width / (CGFloat(130).toRadians())
let arc = CGFloat.pi * 2 * proportion / 100 // i.e. the proportion of a full circle
// Start a mutable path
let cPath = UIBezierPath()
// Move to the centre
cPath.move(to: centre)
// Draw a line to the circumference
cPath.addLine(to: CGPoint(x: centre.x + radius * cos(startAngle), y: centre.y + radius * sin(startAngle)))
// NOW draw the arc
cPath.addArc(withCenter: centre, radius: radius, startAngle: startAngle, endAngle: arc + startAngle, clockwise: true)
// Line back to the centre, where we started (or the stroke doesn't work, though the fill does)
cPath.addLine(to: CGPoint(x: centre.x, y: centre.y))
return cPath
}
override func draw(_ rect: CGRect) {
// let endAngle = percent == 1.0 ? 0 : (percent * 180) + 180
path = UIBezierPath(arcCenter: CGPoint(x: self.frame.size.width/2, y: self.frame.size.height/2),
radius: self.frame.size.height/4,
startAngle: CGFloat(180).toRadians(),
endAngle: CGFloat(0).toRadians(),
clockwise: true)
percentPath = UIBezierPath(arcCenter: CGPoint(x: self.frame.size.width/2, y: self.frame.size.height/2),
radius: self.frame.size.height/4,
startAngle: CGFloat(180).toRadians(),
endAngle: CGFloat(0).toRadians(),
clockwise: true)
let shapeLayer = CAShapeLayer()
shapeLayer.path = self.path.cgPath
shapeLayer.strokeColor = UIColor(red: 110 / 255, green: 78 / 255, blue: 165 / 255, alpha: 1.0).cgColor
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.lineWidth = 5.0
shapeLayer.lineCap = .round
self.layer.addSublayer(shapeLayer)
percentLayer.path = self.percentPath.cgPath
percentLayer.strokeColor = UIColor(red: 255 / 255, green: 93 / 255, blue: 41 / 255, alpha: 1.0).cgColor
percentLayer.fillColor = UIColor.clear.cgColor
percentLayer.lineWidth = 8.0
// percentLayer.strokeEnd = CGFloat(percent)
percentLayer.lineCap = .round
self.layer.addSublayer(percentLayer)
// n.b. as #MartinR points out `cPath.close()` does the same!
// circle shape
circleShape.path = gradientBezierPath(percent: 1.0).cgPath//cPath.cgPath
circleShape.strokeColor = UIColor.clear.cgColor
circleShape.fillColor = UIColor.green.cgColor
self.layer.addSublayer(circleShape)
gradient.frame = frame
gradient.mask = circleShape
gradient.type = .radial
gradient.colors = [UIColor(red: 255 / 255, green: 93 / 255, blue: 41 / 255, alpha: 0.0).cgColor,
UIColor(red: 255 / 255, green: 93 / 255, blue: 41 / 255, alpha: 0.0).cgColor,
UIColor(red: 255 / 255, green: 93 / 255, blue: 41 / 255, alpha: 0.4).cgColor]
gradient.locations = [0, 0.35, 1]
gradient.startPoint = CGPoint(x: 0.49, y: 0.55) // increase Y adds more orange from top to bottom
gradient.endPoint = CGPoint(x: 0.98, y: 1) // increase x pushes orange out more to edges
self.layer.addSublayer(gradient)
//myTextLayer.string = "\(Int(percent * 100))"
myTextLayer.backgroundColor = UIColor.clear.cgColor
myTextLayer.foregroundColor = UIColor.white.cgColor
myTextLayer.fontSize = 85.0
myTextLayer.frame = CGRect(x: (self.frame.size.width / 2) - (self.frame.size.width/8), y: (self.frame.size.height / 2) - self.frame.size.height/8, width: 120, height: 120)
self.layer.addSublayer(myTextLayer)
}
This produces the following in a playground which is pretty close to what i'm aiming for:
The problem comes when trying to animate the change in the gauge value. I can animate the percentLayer pretty easy with modifying strokeEnd, but animating the circleShape.path for the gradient results in some non-smooth animations if there's a large change in the percent value of the gauge. Here's the function i use to animate both layers (it's called on a timer every 2 seconds right now to simulate gauge value changes).
func randomPercent() {
let random = CGFloat.random(in: 0.0...1.0)
// Animate the percent layer
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.fromValue = percentLayer.strokeEnd
animation.toValue = random
animation.duration = 1.5
percentLayer.strokeEnd = random
percentLayer.add(animation, forKey: nil)
// Animate the gradient layer
let newShapePath = gradientBezierPath(percent: random)
let gradientAnimation = CABasicAnimation(keyPath: "path")
gradientAnimation.duration = 1.5
gradientAnimation.toValue = newShapePath
gradientAnimation.fromValue = circleShape.path
circleShape.path = newShapePath.cgPath
self.circleShape.add(gradientAnimation, forKey: nil)
myTextLayer.string = "\(Int(random * 100))"
}
Notice how when the animation is done with small changes in the value, the animation looks good. However when there's a large change the gradient animation doesn't look natural at all. Any ideas on how to improve this? Or maybe is it possible to animate a different keyPath for better performance? Any help would be greatly appreciated!
You can't use the Bezier path addArc() function to animate an arc and change the arc distance.
The problem is control points. In order for an animation to work smoothly, the starting and ending shape must have the same number and type of control points. Under the covers, the UIBezierPath (and CGPath) objects create arcs approximating a circle by combining Bezier curves (I don't remember if it uses Quadratic or Cubic Bezier curves.) The entire circle is made up of multiple connected Bezier curves ("Bezier" the mathematical spline function, not UIBeizerPath, which is a UIKit function that creates shapes that can include Bezier paths.) I seem to remember a Bezier approximation of a circle is made up of 4 linked cubic Bezier curves. (See this SO answer for a discussion of what that looks like, if you're interested.)
Here is my understanding of how it works. (I might have the details wrong, but it illustrates the problem in any case.) As you move from <= 1/4 of a full circle to > 1/4 of a full circle, the arc function will use first 1 cubic Bezier section, then 2. At the transition from <= 1/2 of a circle to > 1/2 of a circle, it will shift to 3 Bezier curves, and at the transition from <= 3/4 of a circle to > 3/4 of a circle, it will switch to 4 Bezier curves.
The solution:
You are on the right track with using strokeEnd. Always create your shape as the full circle, and set strokeEnd to something less than 1. That will give you a part of a circle, but in a way that you can animate smoothly. (You can animate strokeStart as well.)
I've animated circles just like you describe using CAShapeLayer and strokeEnd (It was a number of years ago, so it was in Objective-C.) I wrote an article here on OS on using the approach to animate a mask on a UIImageView and create a "clock wipe" animation. If you have an image of your full shaded circle you could use that exact approach here. (You should be able to add a mask layer to any UIView's content layer or other layer, and animate that layer as in my clock wipe demo. Let me know if you need help deciphering the Objective-C.
Here is the sample clock wipe animation I created:
Note that you can use this effect to mask any layer, not just an image view.
EDIT: I posted an update to my clock wipe animation question and answer with a Swift version of the project.
You can get to the new repo directly at https://github.com/DuncanMC/ClockWipeSwift.
For your application I would set up the parts of your gauge that you need to animate as a composite of layers. You'd then attach a CAShapeLayer based mask layer to that composite layer and add a circle arc path to that shape layer and animate the strokeEnd as shown in my sample project. My clock wipe animation reveals the image like the sweep of a clock hand from the center of the layer. In your case you'd center the arc on the bottom center of your layer, and only use a half-circle arc in your shape layer. Using a mask that way would give you a sharp-edged crop to your composited layer. you'd lose the round end caps on your red arc. To fix that you'd have to animate the red arc as it's own shape layer (using strokeEnd) and animate the gradient fill's arc strokeEnd separately.

Is it possible to draw a dash line without using UIBezierPath

I know use UIBezierPath() to draw a dash line like:
let path = UIBezierPath()
path.setLineDash([CGFloat(4), CGFloat(4)], count: 2, phase: 0)
path.lineCapStyle = CGLineCap.round
path.move(to: startPoint)
path.addLine(to: endPoint)
path.stroke()
It works fine. But how could I can draw a dash line in context? Like below code can draw a solid line no matter if i add
context.setLineDash(phase: 3, lengths: [3,2])
The whole code:
override func draw(_ rect: CGRect) {
if let context = UIGraphicsGetCurrentContext() {
let startPoint = CGPoint(x: 50, y: 10)
let endPoint = CGPoint(x: rect.width-100, y: 10)
context.setLineDash(phase: 3, lengths: [3,2])
context.setLineWidth(10)
context.move(to: startPoint)
context.addLine(to: endPoint)
context.setStrokeColor(UIColor.red.cgColor)
context.setLineCap(.round)
context.strokePath()
}
}
The result is:
Anything wrong?
Think about it...
The line width is 10.
The line cap is round.
So the radius of the line cap is 5.
N.B. The line ends at the centre point of the line cap (not at the end of the cap).
The length of each dash is 3 and the gap between the lines is 2.
So the radius of the cap is much much bigger than the gap between the lines. So each line is overlapping to the next one.
Try making the line lengths like...
[3, 12]
That should make the lines 3 points long with a cap radius of 5 and then a gap between the ends of the caps of 2 (12 - 5 - 5).

Hide part of UIBezierPath

I have 3 UIBezierPath with 2 circle and a line running from 1 circle's center to the other and it looks like the bottom picture. I want to hide the part of the line inside the circle like the top picture. Is there any easy way to do this?
My strategy would be to draw a invisible line from the centers and then draw a black line from the circumference of the 2 circles since I know the slopes etc but it seems like too much work.
private func pathForBoxCircle1() -> UIBezierPath {
let circlePath = UIBezierPath(arcCenter:circle1BoxCurrentCenter, radius: 25, startAngle: 0.0, endAngle: CGFloat(2*M_PI), clockwise: false)
//circlePath.fill()
pathBoxCircle1Global = circlePath
return circlePath
}
private func pathForBoxCircle2() -> UIBezierPath {
let circlePath = UIBezierPath(arcCenter:circle2BoxCurrentCenter, radius: 25, startAngle: 0.0, endAngle: CGFloat(2*M_PI), clockwise: false)
//circlePath.fill()
pathBoxCircle2Global = circlePath
return circlePath
}
private func pathForHorizonLine() -> UIBezierPath {
let path = UIBezierPath()
path.move(to: circle1BoxCurrentCenter)
path.addLine(to: circle2BoxCurrentCenter)
path.lineWidth = 5.0
//pathHorizonLineGlobal = path
return path
}
override func draw(_ rect: CGRect) {
pathForBoxCircle1().stroke()
pathForBoxCircle2().stroke() // same as stroke()
pathForHorizonLine().stroke()
}
You can't mix transparent and opaque lines in the same shape. You are going to have to draw 2 circles and then the line segment from the outside of the first circle to the outside of the 2nd circle.
To do that you'll need trig, or perhaps Pythagoras, to calculate the coordinates of the points where your connecting lines intersect your 2 circles.
If C1 is your first circle, C2 is your 2nd circle, C1 is at (C1.x, C1.y), C2 is at (C2.x, C2.y), the radius of C1 is R1, and the radius of C2 is R2, then the pseudo-code would look something like this:
angle1 = atan2(C1.y - C2y, C1.x - C2.x)
angle2 = atan2(C2.y - C1.y, C2.x - C1.x)
xOffset1 = R1 * cos(angle1)
yOffset1 = R1 * sin(angle1)
point1 = (C1.x + xOffset1, C1.y + yOffset1)
xOffset2 = R2 * cos(angle2)
yOffset2 = R2 * sin(angle2)
point2 = (C2.x + xOffset2, C2.y + yOffset2)
Draw your circles, then draw lines between point1 and point2.
(Note that my trig is a little rusty, and that I sketched this out on a piece of scratch paper. I think it's correct, but it's completely untested.)

Making a very simple graph with uibezierpath

my question was
I want to create a simple line graph with certain values. This is done in a view within the mainviewcontroller. I created a UIview named chart. I pass the data to the chart when its retrieved from the API. I figured out how to draw the axis but I am stuck now. I cant find anything on google on how to set labels on intervals and to make the points appear dynamically.
draw the xasis and its labels.
draw the dots in the graph.
My salution
i figured out how to do all the things i asked for.
The code I have now:
class ChartView: UIView {
//some variables
var times: [String] = []
var AmountOfRain: [Double] = []
let pathy = UIBezierPath()
let pathx = UIBezierPath()
var beginwitharray = Array<CGFloat>()
// Only override draw() if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func draw(_ rect: CGRect) {
// Drawing code
//draw the y line
pathy.move(to: CGPoint(x: 30, y: 10))
pathy.addLine(to: CGPoint(x: 30, y: 10))
pathy.addLine(to: CGPoint(x: 30, y: frame.size.height - 30))
UIColor.black.setStroke()
pathy.lineWidth = 1.0
pathy.stroke()
//draw the x line
pathx.move(to: CGPoint(x: 30, y: frame.size.height - 30))
pathx.addLine(to: CGPoint(x: 30, y: frame.size.height - 30))
pathx.addLine(to: CGPoint(x: frame.size.width - 30, y: frame.size.height - 30))
UIColor.black.setStroke()
pathx.lineWidth = 1.0
pathx.stroke()
//when the data arrives form the SUPER slow duienradar API refresh it with the data
if beginwitharray != []{
//remove the label retriving data
let label = viewWithTag(1)
DispatchQueue.main.sync {
label?.removeFromSuperview()
}
//create the dots in the graph
var point = CGPoint()
//simple way to do 2 loop in 1 loop.
var intforbeginarray = 0
let stoke = UIBezierPath()
//get the first 6 itmes out of the rain array cuz of space issues
let first6aumountarray = AmountOfRain[0...5]
stoke.move(to: CGPoint(x: 30, y: self.frame.size.height - 30))
//loop trough the data in the amounts array
for amount in first6aumountarray{
//determen the hight of the dot
let InitialHeight = (CGFloat(amount) * (self.frame.size.height - 30))/6
let pointHeight = (frame.size.height - 30) - InitialHeight
//make the point so we can draw it using UIbezierpath()
point = CGPoint(x: beginwitharray[intforbeginarray] + 20, y: pointHeight)
intforbeginarray += 1
//create the dot
let dot = UIBezierPath()
dot.addArc(withCenter: point, radius: CGFloat(5), startAngle: CGFloat(0), endAngle: CGFloat(360), clockwise: true)
UIColor.black.setFill()
dot.lineWidth = 30
dot.fill()
//create the line between dots will give a warning on the last one cuz the last one doenst go anyway
stoke.addLine(to: point)
stoke.move(to: point)
stoke.lineWidth = 1
UIColor.black.setStroke()
}
//make the strokes
stoke.stroke()
}
}
func getvalues(RainData: [Double], TimesData:[String]){
//assing the data to the subview
self.AmountOfRain = RainData
self.times = TimesData
//xaxis values
let maxint = [0, 1, 2, 3, 4, 5, 6]
//calculate the hight spacing to fit the graph
let heightperstep = ((self.frame.size.height - 5)/6)-5
var beginheight = self.frame.size.height - 35
//calculate the width spacing to fit the graph
let widthperstep = ((self.frame.size.width - 5)/6)-5
var beginwith = CGFloat(30)
//extra check to see if we have data at all.
if times != []{
//get the first 6 items out of the times array for use in our graph
let first6 = times[0...5]
//draw the label on the main queue
DispatchQueue.main.sync {
//draw the xaxis labels accroding to the spacing
for number in maxint{
let label = UILabel(frame: CGRect(x: 5, y: beginheight, width: 25, height: 15))
label.text = "\(number)"
self.addSubview(label)
beginheight = beginheight - heightperstep
}
//draw the yaxis labels according to the spacing
for time in first6{
let label = UILabel(frame: CGRect(x: beginwith, y: self.frame.size.height - 20, width: 55, height: 15))
label.text = time
self.addSubview(label)
beginwitharray.append(beginwith)
beginwith = beginwith + widthperstep
}
}
}
//redrawthe graph with new data.
setNeedsDisplay()
}}
Any help would be appreciated. I also can't use a lib or a pod since this is a school project and I need to create a simple graph.
EDIT:
Completed my code, cleared up an error when running this code
What I did first was to draw the x-asis and the y-axis. After this I considered reasonable values for the aumountofrain data. this turns out cannot really be higher then 6. Since I could fit around 6 labels in the space I have the steps where easy go down by 1 till I hit 0. The calculations I did are for my specific frame height. After I figured it all out and the padding for the y-asxis. It was a matter of figuring out how to get the dots in the right place. Since I already have the data in the beginwitharray I just needed to calculate the height. Then it was simply loop trough the data and draw each dot. Then I just had to connect the dots using the uibezierpath.
i hope my troubles will save someone a lot of time when they read how i done it.
This might be helpful: Draw Graph curves with UIBezierPath
Essentially what you need to do is for every data set you have you need to know the y-axis range of values and based on those ranges assign each value a CGFloat value (in your case inches of rain needs to correlate to a certain CGFloat value). Let's say you have your set amountOfRain = [0.1, 1.3, 1.5, 0.9, 0.1, 0] so your range is var rangeY = amountOfRain.max() - amountOfRain.min(). now lets find out where your first data point 0.1 should go on your graph by converting inches of rain to a CGFloat value that corresponds to the axis you've drawn already, this equation is just basic algebra: let y1 = (amountOfRain[0]/rangeY)*((frame.size.height-30) - 10) + 10 now it looks like your rain samples are at regular intervals so maybe let x1:CGFloat = 10 now you can add a dot or something at the CGPoint corresponding with (x1,y1). If you did this with all the data points it would create a graph that has your maximum value at the top of the graph and minimum value at the bottom. Good Luck!

How to create graph pies with different sizes using bézier paths in swift?

I want to make a nice graphic pie with 8 equal slices, that can be individually scaled or resized depending on an Int or something like this. This would look something like below just that all the slices should be equally cut:
I have tried this in Objective-C but it makes just one slice:
-(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;
}
How can I achieve that graph in swift?
Break the problem into logical pieces.
You have wedges of different arc widths. All those radii need to add up to a full circle. I assume they represent fractions of something that adds up to 100%. Do you want a specific order? If so, map your fractions in the order you want, such that they all add up to 100%.
Then write code that starts at an angle of zero, and creates arcs that are the specified fraction of 2π. Each one would start at the end of the previous one. Assign a radius that's appropriate based on the data you need.
Now write code that creates closed path segments in a UIBezierPath.
EDIT
You've clarified, and told us that you always want 8 slices of the same width but with different radii.
So you need to write code that takes 8 input values and plots it as 8 arcs with different radius values.
Let's say your input value is an array of floats ranging from 0 to 1. At zero, the wedge is zero-sized. At 1.0, it's the largest circle size that will fit in your view (half the width of a square view.
So you would create an array of 8 floats:
var fractions = [0.5, 0.7, 0.3, 0.1, 1.0 .6, .2, .9]
The code to create a bezier curve with 8 arcs might look something like this:
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()
}
I think the code above would create 8 closed pie-slice paths, but I'm not positive. It might be necessary to add a lineToPoint call between the first moveToPoint call and the arc call.
Edit #2:
Since I am learning Swift, I decided to take this as an exercise and wrote a sample project that generates pie charts using a shape layer and a a custom path created from a UIBezierPath, as outlined above. You can find the sample project on github: PieCharts project on Github
I have managed to solve my problem using Core Graphics! Thanks #duncan-c for your interest.
EDIT:
I have dropped my first solution in the favour of #duncan-c's solution, that works better for my needs!
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)
}
}
And then subclassd the UIView where I needed using:
#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
}

Resources