Please, help! How can I make a transparent outline for circles like this (
so that the background shows through)?
I tried using a mask, but this code does not work..
enter image description here
Perhaps there are some other solutions?
My code:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let backgroundImage = UIImageView(frame: UIScreen.main.bounds)
backgroundImage.image = UIImage(named: "background")
backgroundImage.contentMode = .scaleAspectFill
view.addSubview(backgroundImage)
view.sendSubviewToBack(backgroundImage)
// Параметры для кругов
let circleSize: CGFloat = 100
let borderWidth: CGFloat = 4
let circleSpacing: CGFloat = 30
var previousCircleView: UIImageView?
for i in 0..<3 {
let circleImageView = UIImageView()
circleImageView.image = UIImage(named: "ggg")
circleImageView.contentMode = .scaleAspectFill
view.addSubview(circleImageView)
let maskLayer = CAShapeLayer()
let circlePath = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: circleSize, height: circleSize))
let borderPath = UIBezierPath(ovalIn: CGRect(x: -borderWidth, y: -borderWidth, width: circleSize + 2 * borderWidth, height: circleSize + 2 * borderWidth))
borderPath.append(circlePath)
borderPath.usesEvenOddFillRule = true
maskLayer.path = borderPath.cgPath
maskLayer.fillRule = .evenOdd
circleImageView.layer.mask = maskLayer
circleImageView.snp.makeConstraints { make in
make.width.height.equalTo(circleSize + 2 * borderWidth)
make.centerY.equalToSuperview()
if let previous = previousCircleView {
make.left.equalTo(previous.snp.right).offset(-(circleSize - circleSpacing + borderWidth))
} else {
make.left.equalToSuperview().offset(20)
}
}
previousCircleView = circleImageView
}
}
}
2
Answers
If your goal is a series of crescents, ending in a full circle, creating a shape layer and a mask will involve drawing part-circle arcs, and some trig.
You could instead do this by creating an image view with the contents you want. In that case, you could write code that runs in a loop, drawing a circle in an opaque color, then switching to clear mode and erasing the outline of the circle. Each new circle will erase part of the previous circle, but the last circle won’t be clipped. That’s what your sample image shows.
Here is the code I wrote to create that image, loosely based on your starting code:
Here is a sample project on Github that creates the image below:
Each of those shapes is composed of two arcs. The only trick, requiring a little trigonometry, is to calculate the start and end angle for each. E.g., you can do something like:
Resulting in: