I'm developing an app. I haven't completed my apprenticeship of Swift 2.2/3.0 and I'm in search of some answers.
First: I am using PaintCode to generate the start of Swift code. I made a drawing with the following properties:
Code Swift:
func drawSpeedView(strokeGap strokeGap: CGFloat = 30, strokeDash: CGFloat = 4, strokePhase: CGFloat = 0, strokeWidth: CGFloat = 31, strokeStartAngle: CGFloat = 225, strokeEndAngle: CGFloat = 315) {
//// General Declarations
let context = UIGraphicsGetCurrentContext()
//// DashedLarge Drawing
let dashedLargeRect = CGRect(x: 14.5, y: 17.5, width: 291, height: 291)
let dashedLargePath = UIBezierPath()
dashedLargePath.addArcWithCenter(CGPoint(x: dashedLargeRect.midX, y: dashedLargeRect.midY), radius: dashedLargeRect.width / 2, startAngle: -strokeStartAngle * CGFloat(M_PI)/180, endAngle: -strokeEndAngle * CGFloat(M_PI)/180, clockwise: true)
UIColor.blackColor().setStroke()
dashedLargePath.lineWidth = strokeWidth
CGContextSaveGState(context)
CGContextSetLineDash(context, strokePhase, [strokeDash, strokeGap], 2)
dashedLargePath.stroke()
CGContextRestoreGState(context)
}
My problem:
This code is optimized for iPhone 5.
For the proportion of dotted numbers, I need to create a calculation for the value of strokeDash
for iPhone 6/6s and 6+/6s+
What I need: I have no knowledge base to mount a circumference calculation yet.
I need a calculation for replace the line:
CGContextSetLineDash(context, strokePhase, [strokeDash, strokeGap], 2)
to replace with a decimal number able to put 12/6/15 dashed around the circle, no matter the perimeter of circle.
Does anyone have a solution to my problem?
Where do I start?
As you can see from the line (from your code snippet):
let dashedLargeRect = CGRect(x: 14.5, y: 17.5, width: 291, height: 291)
the drawing space is defined of width 291 points and height 291 points.
Hardcoding these numbers is a bad idea because, as you've noticed, it means that the code would work well only on certain devices and not in others.
To fix this issue you can just grab these resolutions dynamically by declaring the following functions:
func windowHeight() -> CGFloat {
return UIScreen.mainScreen().applicationFrame.size.height
}
func windowWidth() -> CGFloat {
return UIScreen.mainScreen().applicationFrame.size.width
}
then you can create dashedLargeRect
for example:
let dashedLargeRect = CGRect(x: 14.5, y: 17.5, width: windowWidth()-20, height: windowHeight()-20)
This way you make your code device-agnostic that is always good practice. (please take note that I haven't touched the CGRect
"origin", a.k.a. the x
,y
parameters, consider that your homework :) ).
If I understand correctly, you want to know how to draw that dashed arc.
The secret lays on the line
dashedLargePath.addArcWithCenter(CGPoint(x: dashedLargeRect.midX, y: dashedLargeRect.midY), radius: dashedLargeRect.width / 2, startAngle: -strokeStartAngle * CGFloat(M_PI)/180, endAngle: -strokeEndAngle * CGFloat(M_PI)/180, clockwise: true)
You can see the addArcWithCenter documentation here, let me simplify it for you:
let arcCenter = CGPoint(x: dashedLargeRect.midX, y: dashedLargeRect.midY)
let radius = dashedLargeRect.width / 2
let startAngle = -strokeStartAngle * CGFloat(M_PI)/180
let endAngle = -strokeEndAngle * CGFloat(M_PI)/180
dashedLargePath.addArcWithCenter(arcCenter,
radius: radius,
startAngle: startAngle,
endAngle: endAngle,
clockwise: true)
now it should be much clearer what this code does, in case that you would like to draw another line over this one (for example to display the car speed, wind speed, air pressure, etc) all you have to do is call a similar function with a smaller/bigger radius and, probably, a different line style (a.k.a. change the CGContextSetLineDash
, dashedLargePath.lineWidth
, and UIColor.blackColor().setStroke()
lines).