Adding confetti animation behind the human/Animal body to a Video - swift

I want to add confetti animation to a video so that when any animal/human appears then confetti animation should be running behind the human/animal's body. I used following code but here confetti is running as overlay in video.
import UIKit
import QuartzCore
class ConfettiView: UIView {
var emitter: CAEmitterLayer!
var colors: [UIColor]!
var intensity: Float!
private var active : Bool = false
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
func setup() {
colors = [UIColor.red,
UIColor.green,
UIColor.blue
]
intensity = 0.2
active = false
}
func startConfetti() {
emitter = CAEmitterLayer()
emitter.emitterPosition = CGPoint(x: frame.size.width / 2.0, y: -20)
emitter.emitterShape = CAEmitterLayerEmitterShape.line
emitter.emitterSize = CGSize(width: frame.size.width, height: 1)
var cells = [CAEmitterCell]()
for color in colors {
cells.append(confettiWithColor(color: color))
}
emitter.emitterCells = cells
layer.addSublayer(emitter)
active = true
}
func stopConfetti() {
emitter?.birthRate = 0
active = false
}
func confettiWithColor(color: UIColor) -> CAEmitterCell {
let confetti = CAEmitterCell()
confetti.birthRate = 10.0 * intensity
confetti.lifetime = 180.0 * intensity
confetti.lifetimeRange = 0
confetti.color = color.cgColor
confetti.velocity = CGFloat(350.0 * intensity)
confetti.velocityRange = CGFloat(40.0 * intensity)
confetti.emissionLongitude = CGFloat(Double.pi)
confetti.emissionRange = 0.4
confetti.spin = CGFloat(3.5 * intensity)
confetti.spinRange = 0.0
confetti.scale = 0.1
confetti.contents = UIImage(named: "image")?.cgImage
return confetti
}
}
// then I add this confettiView as a subView of VidePlayerView
I need to show/export video with confetti like this.
Watch it. Here confetti is running behind the woman.

Related

How to use CAEmitterLayer on macOS in a SwiftUI app using NSViewRepresentable

I want to use a CAEmitterLayer within a macOS app that is based on SwiftUI.
Problem: The layer itself is perfectly visible, but it doesn’t emit any particles.
→ Here’s my demo project on GitHub
I basically built a NSViewRepresentable for a custom class EmitterNSView: NSView that handles the emitter layer itself.
final class EmitterNSView: NSView {
private let emitterLayer: CAEmitterLayer = {
let layer = CAEmitterLayer()
layer.backgroundColor = NSColor.green.withAlphaComponent(0.33).cgColor
return layer
}()
private let emitterCells: [CAEmitterCell] = {
// https://developer.apple.com/documentation/quartzcore/caemitterlayer
let cell = CAEmitterCell()
cell.name = "someParticle"
cell.birthRate = 10
cell.lifetime = 5.0
cell.velocity = 100
cell.velocityRange = 50
cell.emissionLongitude = 0.0
cell.emissionRange = CGFloat.pi * 2.0
cell.spinRange = 5
cell.scale = 1.0
cell.scaleRange = 0.25
cell.alphaSpeed = 0.25
cell.contents = NSImage(named: "whiteParticle.png")!.cgImage
cell.color = NSColor.systemPink.cgColor
cell.xAcceleration = 4
cell.yAcceleration = 3
cell.zAcceleration = 2
return [cell]
}()
override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
self.wantsLayer = true
self.layer = CALayer()
self.layer?.autoresizingMask = [.layerWidthSizable, .layerHeightSizable]
self.configureEmitterLayer()
self.layer?.addSublayer(self.emitterLayer)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layout() {
super.layout()
self.configureEmitterLayer()
}
override func updateLayer() {
super.updateLayer()
self.configureEmitterLayer()
}
func configureEmitterLayer() {
self.emitterLayer.frame = self.frame
self.emitterLayer.autoresizingMask = [.layerHeightSizable, .layerWidthSizable]
self.emitterLayer.masksToBounds = false
self.emitterLayer.drawsAsynchronously = true
self.emitterLayer.emitterMode = .points
self.emitterLayer.birthRate = 2
self.emitterLayer.emitterShape = CAEmitterLayerEmitterShape.line
self.emitterLayer.emitterSize = CGSize(width: frame.width * 0.5, height: frame.height * 0.5)
self.emitterLayer.emitterPosition = CGPoint.zero
self.emitterLayer.renderMode = CAEmitterLayerRenderMode.additive
self.emitterLayer.emitterCells = self.emitterCells
self.emitterLayer.zPosition = 10
self.emitterLayer.beginTime = CACurrentMediaTime()
self.emitterLayer.speed = 1.5
self.emitterLayer.emitterCells = self.emitterCells
}
}
The fact that I can clearly see the green background of the layer within the app indicates that something is wrong with the cells? Feeling lost at this point.
Very similar implementations in UIKit work just fine.
How can I use CAEmitterLayer on macOS within a SwiftUI based app?
Use cgImage(forProposedRect:context:hints:) while casting NSImage to a CGImage.
cell.contents = NSImage(named:"whiteParticle.png").flatMap {
return $0.cgImage(forProposedRect: nil, context: nil, hints: nil)
}

Swift: Make the outline of a UIView sketch-like

I want to make the outlines of a UIView look "wavey" like someone drew them.
I have this example from PowerPoint, which allows to do it (should work with any size and corner radius):
Currently this is what I have:
myView.layer.borderWidth = 10
myView.layer.borderColor = UIColor.blue.cgColor
myView.layer.cornerRadius = 5 // Optional
Thank
You can create "wavy" lines by using a UIBezierPath with a combination of quad-curves, lines, arcs, etc.
We'll start with a simple line, one-quarter of the width of the view:
Our path would consist of:
move to 0,0
add line to 80,0
If we change that to a quad-curve:
Now we're doing:
move to 0,0
add quad-curve to 80,0 with control point 40,40
If we add another quad-curve going the other way:
Now we're doing:
move to 0,0
add quad-curve to 80,0 with control point 40,40
add quad-curve to 160,0 with control point 120,-40
and we can extend that the width of the view:
of course, that doesn't look like your "sketch" target, so let's change the control-point offsets from 40 to 2:
Now it looks a bit more like a hand-draw "sketched" line.
It's too uniform, though, and it's partially outside the bounds of the view, so let's inset it by 8-pts and, instead of four 25% segments, we'll use (for example) five segments of these widths:
0.15, 0.2, 0.2, 0.27, 0.18
If we take the same approach to go down the right-hand side, back across the bottom, and up the left-hand side, we can get this:
Here's some example code to produce that view:
class SketchBorderView: UIView {
let borderLayer: CAShapeLayer = CAShapeLayer()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() -> Void {
borderLayer.fillColor = UIColor.clear.cgColor
borderLayer.strokeColor = UIColor.blue.cgColor
layer.addSublayer(borderLayer)
backgroundColor = .yellow
}
override func layoutSubviews() {
let incrementVals: [CGFloat] = [
0.15, 0.2, 0.2, 0.27, 0.18,
]
let lineOffsets: [[CGFloat]] = [
[ 1.0, -2.0],
[-1.0, 2.0],
[-1.0, -2.0],
[ 1.0, 2.0],
[ 0.0, -2.0],
]
let pth: UIBezierPath = UIBezierPath()
// inset bounds by 8-pts so we can draw the "wavy border"
// inside our bounds
let r: CGRect = bounds.insetBy(dx: 8.0, dy: 8.0)
var ptDest: CGPoint = .zero
var ptControl: CGPoint = .zero
// start at top-left
ptDest = r.origin
pth.move(to: ptDest)
// we're at top-left
for i in 0..<incrementVals.count {
ptDest.x += r.width * incrementVals[i]
ptDest.y = r.minY + lineOffsets[i][0]
ptControl.x = pth.currentPoint.x + ((ptDest.x - pth.currentPoint.x) * 0.5)
ptControl.y = r.minY + lineOffsets[i][1]
pth.addQuadCurve(to: ptDest, controlPoint: ptControl)
}
// now we're at top-right
for i in 0..<incrementVals.count {
ptDest.y += r.height * incrementVals[i]
ptDest.x = r.maxX + lineOffsets[i][0]
ptControl.y = pth.currentPoint.y + ((ptDest.y - pth.currentPoint.y) * 0.5)
ptControl.x = r.maxX + lineOffsets[i][1]
pth.addQuadCurve(to: ptDest, controlPoint: ptControl)
}
// now we're at bottom-right
for i in 0..<incrementVals.count {
ptDest.x -= r.width * incrementVals[i]
ptDest.y = r.maxY + lineOffsets[i][0]
ptControl.x = pth.currentPoint.x - ((pth.currentPoint.x - ptDest.x) * 0.5)
ptControl.y = r.maxY + lineOffsets[i][1]
pth.addQuadCurve(to: ptDest, controlPoint: ptControl)
}
// now we're at bottom-left
for i in 0..<incrementVals.count {
ptDest.y -= r.height * incrementVals[i]
ptDest.x = r.minX + lineOffsets[i][0]
ptControl.y = pth.currentPoint.y - ((pth.currentPoint.y - ptDest.y) * 0.5)
ptControl.x = r.minX + lineOffsets[i][1]
pth.addQuadCurve(to: ptDest, controlPoint: ptControl)
}
borderLayer.path = pth.cgPath
}
}
and an example controller:
class SketchTestVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let v = SketchBorderView()
v.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(v)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
v.centerXAnchor.constraint(equalTo: g.centerXAnchor),
v.centerYAnchor.constraint(equalTo: g.centerYAnchor),
v.widthAnchor.constraint(equalToConstant: 320.0),
v.heightAnchor.constraint(equalTo: v.widthAnchor),
])
}
}
Using that code, though, we still have too much uniformity, so in actual use we'd want to randomize the number of segments, the widths of the segments, and the control-point offsets.
Of course, to get your "rounded rect" you'd want to add arcs at the corners.
I expect this should get you on your way though.
use this extension to solve the issue
import Foundation
import UIKit
extension UIView {
func dropShadow(scale: Bool = true) {
layer.masksToBounds = false
layer.shadowColor = UIColor.black.cgColor
layer.shadowOpacity = 0.2
layer.shadowOffset = .zero
layer.shadowRadius = 5
layer.shouldRasterize = true
layer.rasterizationScale = scale ? UIScreen.main.scale : 1
}
#IBInspectable
var cornerRadius: CGFloat {
get {
return layer.cornerRadius
}
set {
layer.cornerRadius = newValue
layer.masksToBounds = newValue > 0
}
}
#IBInspectable
var borderWidth: CGFloat {
get {
return layer.borderWidth
}
set {
layer.borderWidth = newValue
}
}
#IBInspectable
var borderColor: UIColor? {
get {
let color = UIColor.init(cgColor: layer.borderColor!) //UIColor.init(CGColor: layer.borderColor!)
return color
}
set {
layer.borderColor = newValue?.cgColor
}
}
#IBInspectable
var shadowRadius: CGFloat {
get {
return layer.shadowRadius
}
set {
layer.shadowRadius = newValue
}
}
#IBInspectable
var shadowOpacity: Float {
get {
return layer.shadowOpacity
}
set {
layer.shadowOpacity = newValue
}
}
#IBInspectable
var shadowOffset: CGSize {
get {
return layer.shadowOffset
}
set {
layer.shadowOffset = newValue
}
}
#IBInspectable
var shadowColor: UIColor? {
get {
if let color = layer.shadowColor {
return UIColor(cgColor: color)
}
return nil
}
set {
if let color = newValue {
layer.shadowColor = color.cgColor
} else {
layer.shadowColor = nil
}
}
}
}
it will look like this

CAEmitterLayer Stops Displaying

I adapted this code for SwiftUI to display confetti particles, but sometimes the particle emitter does not work. I've noticed that this often happens after sending to background (not killing the app entirely) and reopening it, or simply letting the app sit for a while then trying again.
I've tried using beginTime as other answers have mentioned (on both the emitter and cells), but that fully breaks things. I've also tried toggling various other emitter properties (birthRate, isHidden). It might have to do with the fact that I'm adapting this with UIViewRepresentable. It seems like the emitter layer just disappears, even though the debug console says its still visible.
class ConfettiParticleView: UIView {
var emitter: CAEmitterLayer!
public var colors: [UIColor]!
public var intensity: Float!
private var active: Bool!
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
func setup() {
colors = [UIColor(Color.red),
UIColor(Color.blue),
UIColor(Color.orange),
]
intensity = 0.7
active = false
emitter = CAEmitterLayer()
emitter.emitterPosition = CGPoint(x: UIScreen.main.bounds.width / 2.0, y: 0) // emit from top of view
emitter.emitterShape = .line
emitter.emitterSize = CGSize(width: UIScreen.main.bounds.width, height: 100) // line spans the whole top of view
// emitter.beginTime = CACurrentMediaTime()
var cells = [CAEmitterCell]()
for color in colors {
cells.append(confettiWithColor(color: color))
}
emitter.emitterCells = cells
emitter.allowsGroupOpacity = false
self.layer.addSublayer(emitter)
}
func startConfetti() {
emitter.lifetime = 1
// i've tried toggling other properties here like birthRate, speed
active = true
}
func stopConfetti() {
emitter.lifetime = 0
active = false
}
func confettiWithColor(color: UIColor) -> CAEmitterCell {
let confetti = CAEmitterCell()
confetti.birthRate = 32.0 * intensity
confetti.lifetime = 15.0 * intensity
confetti.lifetimeRange = 0
confetti.name = "confetti"
confetti.color = color.cgColor
confetti.velocity = CGFloat(450.0 * intensity) // orig 450
confetti.velocityRange = CGFloat(80.0 * intensity)
confetti.emissionLongitude = .pi
confetti.emissionRange = .pi / 4
confetti.spin = CGFloat(3.5 * intensity)
confetti.spinRange = 300 * (.pi / 180.0)
confetti.scaleRange = CGFloat(intensity)
confetti.scaleSpeed = CGFloat(-0.1 * intensity)
confetti.contents = #imageLiteral(resourceName: "confetti").cgImage
confetti.beginTime = CACurrentMediaTime()
return confetti
}
func isActive() -> Bool {
return self.active
}
}
view representable
struct ConfettiView: UIViewRepresentable {
#Binding var isStarted: Bool
func makeUIView(context: Context) -> ConfettiParticleView {
return ConfettiParticleView()
}
func updateUIView(_ uiView: ConfettiParticleView, context: Context) {
if isStarted && !uiView.isActive() {
uiView.startConfetti()
print("confetti started")
} else if !isStarted {
uiView.stopConfetti()
print("confetti stopped")
}
}
}
swiftui view for testing
struct ConfettiViewTest: View {
#State var isStarted = false
var body: some View {
ZStack {
ConfettiView(isStarted: $isStarted)
.ignoresSafeArea()
Button(action: {
isStarted = true
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
isStarted = false
}
}) {
Text("toggle")
.padding()
.background(Color.white)
}
}
}
}

How can I centre a circular progress bar in a UIView using Swift?

I'm having quite a bit of difficulty simply ensuring a circular progress bar is always in the centre of the UIView it is associated to.
This is what is happening:
Ignore the grey region, this is simply the UIView on a placeholder card. The red is the UIView I have added as an outlet to the UIViewController.
Below is the code for the class that I have made:
class CircleProgress: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupView()
}
var progressLyr = CAShapeLayer()
var trackLyr = CAShapeLayer()
var progressClr = UIColor.red {
didSet {
progressLyr.strokeColor = progressClr.cgColor
}
}
var trackClr = UIColor.black {
didSet {
trackLyr.strokeColor = trackClr.cgColor
}
}
private func setupView() {
self.backgroundColor = UIColor.red
let centre = CGPoint(x: frame.size.width/2, y: frame.size.height/2)
let circlePath = UIBezierPath(arcCenter: centre,
radius: 10,
startAngle: 0,
endAngle: 2 * CGFloat.pi,
clockwise: true)
trackLyr.path = circlePath.cgPath
trackLyr.fillColor = UIColor.clear.cgColor
trackLyr.strokeColor = trackClr.cgColor
trackLyr.lineWidth = 5.0
trackLyr.strokeEnd = 1.0
layer.addSublayer(trackLyr)
}
}
The aim is simply to have all 4 edges of the black circle touching the edges of the red square.
Any help is hugely appreciated. I'm thinking it must be too obvious but this has cost me too many hours tonight. :)
The problem is that there is no frame being passed when creating the object. No need for changing anything to your code. For sure you have to change the width and the height to whatever you want.
Here is an example...
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .white
// Add circleProgress
addCircleProgress()
}
private func addCircleProgress() {
let circleProgress = CircleProgress(frame: CGRect(x: self.view.center.x - 50, y: self.view.center.x - 50, width: 100, height: 100))
self.view.addSubview(circleProgress)
}
}
class CircleProgress: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
var progressLyr = CAShapeLayer()
var trackLyr = CAShapeLayer()
var progressClr = UIColor.red {
didSet {
progressLyr.strokeColor = progressClr.cgColor
}
}
var trackClr = UIColor.black {
didSet {
trackLyr.strokeColor = trackClr.cgColor
}
}
private func setupView() {
self.backgroundColor = UIColor.red
let centre = CGPoint(x: frame.size.width/2, y: frame.size.height/2)
let circlePath = UIBezierPath(arcCenter: centre,
radius: 50,
startAngle: 0,
endAngle: 2 * CGFloat.pi,
clockwise: true)
trackLyr.path = circlePath.cgPath
trackLyr.fillColor = UIColor.clear.cgColor
trackLyr.strokeColor = trackClr.cgColor
trackLyr.lineWidth = 5.0
trackLyr.strokeEnd = 1.0
layer.addSublayer(trackLyr)
}
}
A few suggestions:
I’d suggest making this CircularProgress take up the whole view. If you want this to be inset within the view, then, fine, add a property for that. In my example below, I created a property called inset to capture this value.
Make sure to update your path in layoutSubviews. Especially if you use constraints, you want this to respond to size changes. So add these layers from init, but update the path in layoutSubviews.
Don’t reference frame (which is the location within the superview coordinate system). Use bounds. And inset it by half the line width, so the circle doesn’t exceed the bounds of the view.
You created a progress color and progress layer, but didn’t use either one. I’ve guessed you wanted that to show the progress within the track.
You are stroking your path from 0 to 2π. People tend to expect these circular progress views to start from -π/2 (12 o’clock) and progress to 3π/2. So I’ve updated the path to use those values. But use whatever you want.
If you want, you can make it #IBDesignable if you want to see this rendered in IB.
Thus, pulling that together, you get:
#IBDesignable
public class CircleProgress: UIView {
#IBInspectable
public var lineWidth: CGFloat = 5 { didSet { updatePath() } }
#IBInspectable
public var strokeEnd: CGFloat = 1 { didSet { progressLayer.strokeEnd = strokeEnd } }
#IBInspectable
public var trackColor: UIColor = .black { didSet { trackLayer.strokeColor = trackColor.cgColor } }
#IBInspectable
public var progressColor: UIColor = .red { didSet { progressLayer.strokeColor = progressColor.cgColor } }
#IBInspectable
public var inset: CGFloat = 0 { didSet { updatePath() } }
private lazy var trackLayer: CAShapeLayer = {
let layer = CAShapeLayer()
layer.fillColor = UIColor.clear.cgColor
layer.strokeColor = trackColor.cgColor
layer.lineWidth = lineWidth
return layer
}()
private lazy var progressLayer: CAShapeLayer = {
let layer = CAShapeLayer()
layer.fillColor = UIColor.clear.cgColor
layer.strokeColor = progressColor.cgColor
layer.lineWidth = lineWidth
return layer
}()
override init(frame: CGRect = .zero) {
super.init(frame: frame)
setupView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupView()
}
public override func layoutSubviews() {
super.layoutSubviews()
updatePath()
}
}
private extension CircleProgress {
func setupView() {
layer.addSublayer(trackLayer)
layer.addSublayer(progressLayer)
}
func updatePath() {
let rect = bounds.insetBy(dx: lineWidth / 2 + inset, dy: lineWidth / 2 + inset)
let centre = CGPoint(x: rect.midX, y: rect.midY)
let radius = min(rect.width, rect.height) / 2
let path = UIBezierPath(arcCenter: centre,
radius: radius,
startAngle: -.pi / 2,
endAngle: 3 * .pi / 2,
clockwise: true)
trackLayer.path = path.cgPath
trackLayer.lineWidth = lineWidth
progressLayer.path = path.cgPath
progressLayer.lineWidth = lineWidth
}
}
That yields:
Update this function
private func setupView() {
self.backgroundColor = UIColor.red
let centre = CGPoint(x: bounds.midX, y: bounds.midY)
let circlePath = UIBezierPath(arcCenter: centre,
radius: bounds.maxX/2,
startAngle: 0,
endAngle: 2 * CGFloat.pi,
clockwise: true)
trackLyr.path = circlePath.cgPath
trackLyr.fillColor = UIColor.clear.cgColor
trackLyr.strokeColor = trackClr.cgColor
trackLyr.lineWidth = 5.0
trackLyr.strokeEnd = 1.0
layer.addSublayer(trackLyr)
}

How can I add a little white tick to SSRadioButton

The following is my code. I want to add a little white tick to middle when i clicked the button. How can i do that by programming but not using image...
import Foundation
import UIKit
#IBDesignable
class SSRadioButton: UIButton {
private var circleLayer = CAShapeLayer()
private var fillCircleLayer = CAShapeLayer()
override var selected: Bool {
didSet {
toggleButon()
}
}
/**
Color of the radio button circle. Default value is UIColor red.
*/
#IBInspectable var circleColor: UIColor = UIColor.redColor() {
didSet {
circleLayer.strokeColor = circleColor.CGColor
self.toggleButon()
}
}
/**
Radius of RadioButton circle.
*/
#IBInspectable var circleRadius: CGFloat = 5.0
#IBInspectable var cornerRadius: CGFloat {
get {
return layer.cornerRadius
}
set {
layer.cornerRadius = newValue
layer.masksToBounds = newValue > 0
}
}
private func circleFrame() -> CGRect {
var circleFrame = CGRect(x: 0, y: 0, width: 2*circleRadius, height: 2*circleRadius)
circleFrame.origin.x = 0 + circleLayer.lineWidth
circleFrame.origin.y = bounds.height/2 - circleFrame.height/2
return circleFrame
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
initialize()
}
override init(frame: CGRect) {
super.init(frame: frame)
initialize()
}
private func initialize() {
circleLayer.frame = bounds
circleLayer.lineWidth = 2
circleLayer.fillColor = UIColor.clearColor().CGColor
circleLayer.strokeColor = circleColor.CGColor
layer.addSublayer(circleLayer)
fillCircleLayer.frame = bounds
fillCircleLayer.lineWidth = 2
fillCircleLayer.fillColor = UIColor.clearColor().CGColor
fillCircleLayer.strokeColor = UIColor.clearColor().CGColor
layer.addSublayer(fillCircleLayer)
self.titleEdgeInsets = UIEdgeInsetsMake(0, (4*circleRadius + 4*circleLayer.lineWidth), 0, 0)
self.toggleButon()
}
/**
Toggles selected state of the button.
*/
func toggleButon() {
if self.selected {
fillCircleLayer.fillColor = circleColor.CGColor
} else {
fillCircleLayer.fillColor = UIColor.clearColor().CGColor
}
}
private func circlePath() -> UIBezierPath {
return UIBezierPath(ovalInRect: circleFrame())
}
private func fillCirclePath() -> UIBezierPath {
return UIBezierPath(ovalInRect: CGRectInset(circleFrame(), 2, 2))
}
override func layoutSubviews() {
super.layoutSubviews()
circleLayer.frame = bounds
circleLayer.path = circlePath().CGPath
fillCircleLayer.frame = bounds
fillCircleLayer.path = fillCirclePath().CGPath
self.titleEdgeInsets = UIEdgeInsetsMake(0, (2*circleRadius + 4*circleLayer.lineWidth), 0, 0)
}
override func prepareForInterfaceBuilder() {
initialize()
}
}
Something like this?
You could do achieve by using UIBezierPath to draw a couple of lines that make a tick. Unless you were looking for something more fancy or curvy? The answer to this question: Draw a line with UIBezierPath
has a nice little function that simplifies the process of drawing the lines.