Есть ли способ составить маски, используя CAShapeLayer.compositingFilters в Swift? - PullRequest
0 голосов
/ 15 февраля 2019

Я реализую функцию рисования для приложения для iPad.Я использую UIBezierPaths на CAShapeLayers для рисования.Создавая новый CAShapeLayer для каждого события TouchesBegan, я создаю массив «сложенных» CAShapeLayers, которые позволяют мне легко реализовывать отмену и возврат, выдвигая и выдвигая слои в массив и из него.Я также делаю некоторые интересные методы смешивания слоев, используя некоторые CAShapeLayer.compositingFilters.Это все работает очень хорошо.Моя задача - удалить.

Я пытаюсь создать второй массив CAShapeLayers и использовать их для маскировки первой группы.Я могу ДОБАВИТЬ В группу масок, используя ту же технику, что и выше, при рисовании непрозрачным цветом, но не могу удалить непрозрачные области из группы масок.

Я думал, что смогу начать технику маскировки с непрозрачного базового слоя (черного, белого или любого другого).Затем я надеялся нарисовать UIBezierPaths с UIColor.clear.cgColor и объединить или скомбинировать мой нарисованный путь с базовой непрозрачной базовой маской.Это, по сути, должно «стереть» эту область маски и скрыть сложенные слои CAShapeLayers, в которые я рисую.Я не хотел объединять слои маски в изображение, потому что я потерял бы способность легко отменять и повторять, выталкивая и нажимая на массив маски.

Я включил ниже некоторый псевдокод.Любые указатели, помощь или стратегии для решения будут очень признательны!Я работал над этим в течение нескольких недель, и я действительно в замешательстве.Я не могу найти информацию о стратегии, над которой я работаю для этого.Кроме того, если я с самого начала неправильно описываю функциональность рисования и есть более простой способ рисования при сохранении простых отмен / повторов и добавлении стирания, пожалуйста, дайте мне знать.Я полностью открыт для корректировки своего подхода!Спасибо заранее за любую помощь.

// setup the layer hierarchy for drawing    
private func setupView() {
        self.mainDrawLayer = CAShapeLayer()
        self.mainDrawLayer.backgroundColor = UIColor.clear.cgColor
        self.layer.addSublayer(self.mainDrawLayer)

        // set up the mask. add an opaque background so everything shows through to start
        self.maskLayer = CALayer()
        let p = UIBezierPath.init(rect: self.bounds)
        self.maskShapeLayer = CAShapeLayer()
        self.maskShapeLayer?.fillColor = UIColor.black.cgColor
        self.maskShapeLayer?.path = p.cgPath
        self.maskLayer?.addSublayer(self.maskShapeLayer!)

        // apply the mask
        self.layer.mask = self.maskLayer
    }

override public func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)

        guard let touch = touches.first else {
            return
        }

        var erasing = false


        // setup the currentDrawLayer which captures the bezier path
        self.currentDrawLayer = CAShapeLayer()
        self.currentDrawLayer?.lineCap = CAShapeLayerLineCap.round
        self.currentDrawLayer?.fillColor = nil

        // set the ink color to use for drawing
        if let ink = UserDefaults.standard.string(forKey: "ink") {
            self.currentDrawLayer?.strokeColor = UIColor(hex: ink)?.cgColor
        } else {
            self.currentDrawLayer?.strokeColor = UIColor(hex: Constants.inkBlack3)?.cgColor
        }

        if UserDefaults.standard.string(forKey: "ink") == Constants.inkBlack5 {
            // removing the filter makes white overlay other colors
            // this is essentially erasing with a white background
            self.currentDrawLayer?.compositingFilter = nil
        } else {
            // this blend mode ads a whole different feeling to the drawing!
            self.currentDrawLayer?.compositingFilter = "darkenBlendMode"
        }

        // THIS IS THE ERASER COLOR!
        if UserDefaults.standard.string(forKey: "ink") == Constants.inkBlack4 {
            // trying erasing via drawing with clear
            self.currentDrawLayer?.strokeColor = UIColor.clear.cgColor
            // is there a compositingFilter available to 'combine' my clear color with the black opaque mask layer created above?
            self.currentDrawLayer?.compositingFilter = "iDontHaveADamnClueIfTheresOneThatWillWorkIveTriedThemAllItSeems:)"

            erasing = true

        }

        self.currentDrawLayer?.path = self.mainDrawPath.cgPath

        if erasing {
            // add the layer to the masks
            self.maskLayer!.addSublayer(self.currentDrawLayer!)
        } else {
            // add the layer to the drawings
            self.layer.addSublayer(self.currentDrawLayer!)
        }

        let location = touch.location(in: self)

        self.ctr = 0
        self.pts[0] = location
    }
...