Как применить несколько масок к UIView - PullRequest
0 голосов
/ 06 июня 2018

У меня есть вопрос о том, как применить несколько масок к UIView, у которого уже есть маска.

Ситуация:
У меня есть представление с активной маской, которая создаетдыра в левом верхнем углу, это шаблон UIView, который повторно используется везде в проекте.Позже в проекте я хотел бы иметь возможность создать второе отверстие, но на этот раз в правом нижнем углу, без необходимости создания совершенно нового UIView.

Проблема:
Когда я применяю нижнюю маску, она, конечно, заменяет первую, удаляя верхнее отверстие ... Есть ли способ объединить их обе?И в этом отношении объединить любую существующую маску с новой?

Заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 06 июня 2018

Основываясь на ответе @ Sharad, я понял, что повторное добавление прямоугольника представления позволит мне объединить оригинальную и новую маску в одну.

Вот мое решение:

func cutCircle(inView view: UIView, withRect rect: CGRect) {

    // Create new path and mask
    let newMask = CAShapeLayer()
    let newPath = UIBezierPath(ovalIn: rect)

    // Create path to clip
    let newClipPath = UIBezierPath(rect: view.bounds)
    newClipPath.append(newPath)

    // If view already has a mask
    if let originalMask = view.layer.mask,
        let originalShape = originalMask as? CAShapeLayer,
        let originalPath = originalShape.path {

        // Create bezierpath from original mask's path
        let originalBezierPath = UIBezierPath(cgPath: originalPath)

        // Append view's bounds to "reset" the mask path before we re-apply the original
        newClipPath.append(UIBezierPath(rect: view.bounds))

        // Combine new and original paths
        newClipPath.append(originalBezierPath)

    }

    // Apply new mask
    newMask.path = newClipPath.cgPath
    newMask.fillRule = kCAFillRuleEvenOdd
    view.layer.mask = newMask
}
0 голосов
/ 06 июня 2018

Это код, который я использовал в своем проекте, чтобы создать одну окружность и одну маску прямоугольника в UIView, вы можете заменить строку UIBezierPath тем же кодом дуги:

func createCircleMask(view: UIView, x: CGFloat, y: CGFloat, radius: CGFloat, downloadRect: CGRect){
    self.layer.sublayers?.forEach { ($0 as? CAShapeLayer)?.removeFromSuperlayer() }

    let mutablePath      = CGMutablePath()
    mutablePath.addArc(center: CGPoint(x: x, y: y + radius), radius: radius, startAngle: 0.0, endAngle: 2 * 3.14, clockwise: false)
    mutablePath.addRect(view.bounds)
    let path             = UIBezierPath(roundedRect: downloadRect, byRoundingCorners: [.topLeft, .bottomRight], cornerRadii: CGSize(width: 5, height: 5))
    mutablePath.addPath(path.cgPath)

    let mask             = CAShapeLayer()
    mask.path            = mutablePath
    mask.fillRule        = kCAFillRuleEvenOdd
    mask.backgroundColor = UIColor.clear.cgColor


    view.layer.mask      = mask
}

Передайте свой тот же UIView,удаляет предыдущие слои и применяет новые маски к тому же UIView.

Здесь mask.fillRule = kCAFillRuleEvenOdd важно.Если вы заметили, что есть 3 mutablePath.addPath() функций, то, что делает kCAFillRuleEvenOdd, сначала создает отверстие с дугой, затем добавляет Rect границы этого вида, а затем еще одну маску для создания 2-го отверстия.

...