Добавление нескольких путей исключения в CGMutablePath - PullRequest
0 голосов
/ 16 апреля 2019

Я следовал документации правил обмотки , предоставленной для свойства fillRule, которое используется для определения точной точки внутри области или нет. Моя проблема пытается добавить несколько исключений пути в пути, как показано ниже. Я пытался отладить это на детской площадке, но не смог определить, как это работает и что нужно для достижения результата. Проблема возникает, когда я добавляю более одной дуги в одну линию.

Результаты смешные:

enter image description here enter image description here

    let maskView = UIView(frame: UIScreen.main.bounds)
    view.addSubview(maskView)
    maskView.backgroundColor = UIColor.black.withAlphaComponent(0.7)
    //
    let path = CGMutablePath()

    path.addArc(center: CGPoint(x: 20, y: 20),
                radius: 10,
                startAngle: 0, endAngle: 2 * .pi,
                clockwise: false)

    path.addArc(center: CGPoint(x: 220, y: 20),
                radius: 10,
                startAngle:  0, endAngle: 2 * .pi,
                clockwise: false)

    path.addArc(center: CGPoint(x: 100, y: 300),
                radius: 12,
                startAngle: 0, endAngle: 2 * .pi,
                clockwise: false)


    path.addRect(CGRect(origin: .zero, size: UIScreen.main.bounds.size))




    let maskLayer = CAShapeLayer()
    maskLayer.backgroundColor = UIColor.black.cgColor
    maskLayer.path = path
    maskLayer.fillRule = .evenOdd
    maskView.layer.mask = maskLayer

Код, предоставленный Apple, делает это очень легко здесь: Цветочный узор

Ответы [ 2 ]

1 голос
/ 16 апреля 2019

Вы не описываете, чего вы действительно хотите достичь.Я предполагаю, что вы хотите иметь прямоугольник с тремя круглыми отверстиями.

Главное, чтобы понять, что путь может состоять из нескольких подпутей .Каждый подпуть может быть либо закрыт (он заканчивается там, где он начался), либо open (он заканчивается в точке, отличной от того, с которой он начинался).Внутри подпути все отрезки соединены.

Для того, что вы пытаетесь достичь, требуется несколько закрытых подпутей.В противном случае вы не сможете получить несвязанные фигуры.

В одном из ваших примеров очевидно, что три круга были автоматически соединены линиями, что привело к образованию трехглавой.Документация addArc упоминает это:

Если путь уже содержит подпуть, этот метод добавляет линию, соединяющую текущую точку с начальной точкой дуги.

Чтобы создать новый подпуть, либо переместите к началу следующего подпути (используя move), либо закройте предыдущую (используяcloseSubpath).Поэтому средняя часть вашего кода должна выглядеть так:

let path = CGMutablePath()

path.addRect(CGRect(origin: .zero, size: UIScreen.main.bounds.size))
path.closeSubpath

path.addArc(center: CGPoint(x: 20, y: 20),
            radius: 10,
            startAngle: 0, endAngle: 2 * .pi,
            clockwise: false)
path.closeSubpath

path.addArc(center: CGPoint(x: 220, y: 20),
            radius: 10,
            startAngle:  0, endAngle: 2 * .pi,
            clockwise: false)
path.closeSubpath

path.addArc(center: CGPoint(x: 100, y: 300),
            radius: 12,
            startAngle: 0, endAngle: 2 * .pi,
            clockwise: false)
path.closeSubpath
0 голосов
/ 16 апреля 2019

В вашем примере вы настроили только один путь. Однако, чтобы увидеть действующий fillRule, вам потребуется несколько подпутей. Попробуйте сделать следующее:

  • Создайте прямоугольный путь (границы экрана).
  • Создайте свои пути исключения и добавьте их в качестве вспомогательных путей к прямоугольнику (через CGMutablePath.addPath).
  • Используйте путь в вашем maskLayer

См. Следующий игровой код для рабочего примера:

import UIKit
import PlaygroundSupport

class MaskView: UIView {
    override static var layerClass: AnyClass {
        return CAShapeLayer.self
    }

    var highlightedAreas = [CGPath]() {
        didSet {
            setNeedsLayout()
        }
    }

    func setMaskColor(_ color: UIColor) {
        (layer as? CAShapeLayer)?.fillColor = color.cgColor
        (layer as? CAShapeLayer)?.fillRule = CAShapeLayerFillRule.evenOdd
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        frame = superview?.bounds ?? .zero
        let path = makePath()
        (layer as? CAShapeLayer)?.path = path
    }

    private func makePath() -> CGPath {
        let path = CGMutablePath()

        path.addRect(bounds)

        for subPath in highlightedAreas {
            path.addPath(subPath)
        }

        return path
    }
}

class DemoViewController: UIViewController {
    private var mask: MaskView!

    override func viewDidLoad() {
        super.viewDidLoad()
        mask = MaskView()
        mask.backgroundColor = .clear
        view.addSubview(mask)

        mask.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        mask.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        mask.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        mask.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        view.backgroundColor = .green

        let path1 = CGMutablePath()
        path1.addRect(CGRect(x: 50, y: 50, width: 120, height: 80))

        let path2 = CGMutablePath()
        path2.addRect(CGRect(x: 150, y: 110, width: 80, height: 120))

        mask.highlightedAreas = [path1, path2]

        mask.setMaskColor(UIColor(white: 0, alpha: 0.7))
    }
}

let demoController = DemoViewController()

demoController.preferredContentSize = CGSize(width: 300, height: 300)
PlaygroundPage.current.liveView = demoController

В результате получается вид, который выглядит следующим образом:

enter image description here

Вид фона зеленым. Темный цвет - это цвет заливки пути. Путь состоит из большого прямоугольника размером с вид и двух прямоугольных перекрывающихся подпутей. Там, где есть одно перекрытие суб-пути, путь не будет заполнен (четно-нечетное правило заполнения, 2 пути перекрываются). Однако область, где путь и два вспомогательных пути перекрывают цвет заливки, является видимой (перекрытие 3 путей).

...