Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/95.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何使用Swift中的CAShapeLayer为CALayer.SubLayer创建橡皮擦_Ios_Swift_Calayer_Cashapelayer_Eraser - Fatal编程技术网

Ios 如何使用Swift中的CAShapeLayer为CALayer.SubLayer创建橡皮擦

Ios 如何使用Swift中的CAShapeLayer为CALayer.SubLayer创建橡皮擦,ios,swift,calayer,cashapelayer,eraser,Ios,Swift,Calayer,Cashapelayer,Eraser,我一直在到处寻找一个被问了很多次的问题的答案。我花了几个小时浏览SO和Google。必须有一个答案,而不是采取一个高山移动的努力 我正在开发一个矢量绘图应用程序,最终实现了绘图和撤销功能。现在我需要一块橡皮擦 编辑:根据@DonMag的精彩评论,我能够非常接近一块橡皮擦,但有些地方仍然不太对劲。因此,我将尝试解释我的视图和图层在应用程序中是如何显示的,以及我为什么这样做: 从底部视图/图层开始到顶部 BackgroundImageView-我使用此图像视图来保存绘图表面的“背景”。这是一个可以更

我一直在到处寻找一个被问了很多次的问题的答案。我花了几个小时浏览SO和Google。必须有一个答案,而不是采取一个高山移动的努力

我正在开发一个矢量绘图应用程序,最终实现了绘图和撤销功能。现在我需要一块橡皮擦

编辑:根据@DonMag的精彩评论,我能够非常接近一块橡皮擦,但有些地方仍然不太对劲。因此,我将尝试解释我的视图和图层在应用程序中是如何显示的,以及我为什么这样做:

从底部视图/图层开始到顶部

  • BackgroundImageView-我使用此图像视图来保存绘图表面的“背景”。这是一个可以更改的层,可以保存新的“模板”并将其重新调用到中。我将其分开,这样用户就不能擦除绘图表面。而背景由表示不同纸张类型的图层组成

  • MainImageView-我正在使用此图像视图绘制用户启动的所有图形。因此,我触摸并拖动手指,新的CAShapeLayer被添加到图像视图中。这样可以将用户的图形与“图形表面”分开。这也是我希望擦除发生的地方

  • PageImagesView-我使用此视图保存用户可以添加到页面中的图像,并移动/调整它们的大小。我不想让橡皮擦影响图像,但如果在MainImageView中绘制的一条线穿过图像,需要擦除,它应该让图像显示出来,而不是删除图像的部分

  • 我还添加了另一层,试图让橡皮擦工作,并将其称为“橡皮擦图像视图”,并在其中绘制“遮罩”,然后尝试将该遮罩应用于MainImageView。

    这是我的绘图代码,每次调用touchesMoved时都会调用:

    编辑: 将橡皮擦代码添加到我的绘图代码中

    if橡皮擦{
    设linePath=UIBezierPath()
    对于行中的(索引,点)。枚举(){
    如果索引==0{
    中点=cg点(
    x:(点x+点x)/2,
    y:(点y+点y)/2
    )
    linePath.移动(到:中点!)
    }否则{
    中点=cg点(
    x:(点.x+线[索引-1].x)/2,
    y:(点.y+线[索引-1].y)/2
    )
    addQuadCurve(to:middpoint!,controlPoint:line[index-1])
    }
    }
    设maskLayer=CAShapeLayer()
    maskLayer.lineWidth=画笔
    maskLayer.lineCap=.round
    maskLayer.strokeColor=UIColor.black.cgColor
    maskLayer.fillColor=nil
    maskLayer.frame=backgroundImageView.bounds
    maskLayer.path=linePath.cgPath
    //橡皮擦图像视图.layer.addSublayer(backgroundImageView.layer)
    擦除RimageView.layer.addSublayer(maskLayer)
    橡皮擦rimageview.layer.mask=mainImageView.layer
    }
    
    上述代码会导致除“橡皮擦”接触的部分外的所有用户图形消失。我知道我有点不对劲,或者我用的口罩不正确。有人有解决办法吗

    画一些线,看起来很棒

    [

    当我尝试使用橡皮擦时,会发生这种情况

    正如你在上面看到的,我可以画线,但一旦我把橡皮擦放到页面上,它就会删除除我用橡皮擦接触的部分以外的所有内容

    有人知道我哪里出错了吗

    编辑: 如此接近! 当我移动手指时,我能够让橡皮擦去除部分绘制的线条。但它不是使用尺寸绘制,而是在制作形状。它还在使用橡皮擦后,只要我一接触到绘图表面,就会替换所有“已擦除”的部分

    这是我的新橡皮擦代码:

    if eraser {
                //var rect: CGRect = CGRect()
                let linePath = UIBezierPath(rect: mainImageView.bounds)
    
                for (index, point) in line.enumerated() {
                    if index == 0 {
                        midPoint = CGPoint(
                            x: (point.x + point.x) / 2,
                            y: (point.y + point.y) / 2
                        )
                        //rect = CGRect(x: midPoint!.x, y: midPoint!.y, width: brush, height: brush)
                        linePath.move(to: midPoint!)
                    } else {
                        midPoint = CGPoint(
                            x: (point.x + line[index - 1].x) / 2,
                            y: (point.y + line[index - 1].y) / 2
                        )
                        //rect = CGRect(x: midPoint!.x, y: midPoint!.y, width: brush, height: brush)
                        linePath.addQuadCurve(to: midPoint!, controlPoint: line[index - 1])
                    }
                }
    
                let maskLayer = CAShapeLayer()
                maskLayer.lineWidth = brush
                maskLayer.lineCap = .round
                maskLayer.strokeColor = UIColor.clear.cgColor
                maskLayer.fillColor = UIColor.black.cgColor
                maskLayer.opacity = 1.0
                maskLayer.path = linePath.cgPath
                maskLayer.fillRule = .evenOdd
                mainImageView.layer.addSublayer(maskLayer)
                mainImageView.layer.mask = maskLayer
    
            }
    
    func updateTemplate() {
            let templates = TemplatePickerData()
            var loadLayer = templates.loadTemplateIds()
            if loadLayer.count == 0 {
                _ = templates.loadTemplates()
                loadLayer = templates.loadTemplateIds()
            }
            print("this is the template ID: \(templateId)")
            //let templateId = loadLayer[template].value(forKey: "templateId") as! Int
            if template < 0 {
                template = 0
            }
    
            switch template {
            case 0:
                //scrollView.image = UIImage(named: "habitTracker0")!
                scrollView.backgroundImageView.layer.sublayers?.removeAll()
                scrollView.backgroundImageView.layer.addSublayer(drawBullets.drawBullets(coordinates: scrollView.backgroundImageView, bulletColor: UIColor(red: 214.0/255.0, green: 214.0/255.0, blue: 214.0/255.0, alpha: 1.0)))
                scrollView.setNeedsLayout()
                scrollView.layoutIfNeeded()
                scrollView.setNeedsDisplay()
            case 1:
                //scrollView.image = UIImage(named: "monthTemplate0")!
                scrollView.backgroundImageView.layer.sublayers?.removeAll()
                scrollView.backgroundImageView.layer.addSublayer(drawNotes.drawLines(coordinates: scrollView.backgroundImageView, lineColor: UIColor(red: 214.0/255.0, green: 214.0/255.0, blue: 214.0/255.0, alpha: 1.0)))
                scrollView.setNeedsLayout()
                scrollView.layoutIfNeeded()
                scrollView.setNeedsDisplay()
            case 2:
                //scrollView.image = UIImage(named: "habitTracker0")!
                scrollView.backgroundImageView.layer.sublayers?.removeAll()
                scrollView.backgroundImageView.layer.addSublayer(drawNotes2.drawLines(coordinates: scrollView.backgroundImageView, lineColor: UIColor(red: 214.0/255.0, green: 214.0/255.0, blue: 214.0/255.0, alpha: 1.0)))
                scrollView.setNeedsLayout()
                scrollView.layoutIfNeeded()
                scrollView.setNeedsDisplay()
            default:
                if loadLayer.count > template {
                    template = 0
                }
                print("this layer is named: \(loadLayer[template].value(forKey: "templateName") as! String)")
                let layer = loadLayer[template].value(forKey: "templatePath") as! String
                templateId = loadLayer[template].value(forKey: "templateId") as! Int
                let thisTemplate = templates.loadImage(image: layer)
    
                scrollView.backgroundImageView.layer.sublayers?.removeAll()
                scrollView.backgroundImageView.layer.addSublayer(drawBullets.drawBullets(coordinates: scrollView.backgroundImageView, bulletColor: UIColor(red: 214.0/255.0, green: 214.0/255.0, blue: 214.0/255.0, alpha: 1.0)))
                scrollView.backgroundImageView.layer.addSublayer(thisTemplate)
                scrollView.setNeedsLayout()
                scrollView.layoutIfNeeded()
                scrollView.setNeedsDisplay()
            }
            scrollView.setNeedsDisplay()
    
            if optionsMenuView.pageNameTextField.text != "" {
                if isYear {
                    page = optionsMenuView.savePage(journalName: journalName, monthName: nil, weekName: nil, yearName: yearName, yearPosition: yearPosition, pageDrawingPath: pageDrawingPath, originalName: originalYearName, brushColor: 1, brushSize: brushSizeMenuView.brushSlider.value, templateId: templateId, pageDrawing: scrollView.mainImageView.layer)
                } else {
                    page = optionsMenuView.savePage(journalName: journalName, monthName: monthName, weekName: weekName, yearName: nil, yearPosition: nil, pageDrawingPath: pageDrawingPath, originalName: originalWeekName, brushColor: 1, brushSize: brushSizeMenuView.brushSlider.value, templateId: templateId, pageDrawing: scrollView.mainImageView.layer)
                }
            }
            optionsMenuView.templateId = templateId
        }
    
    结果如下:

    有没有办法让橡皮擦像画线一样画

    编辑:应@DonMag的请求,为背景“绘图”添加代码

    import Foundation
    import UIKit
    
    class DrawBulletLayer : UIView {
    
        private var bullet: CAShapeLayer?
    
        func drawBullets(coordinates: UIImageView, bulletColor: UIColor) -> CALayer {
            let bullet = self.bullet ?? CAShapeLayer()
            let bulletPath = UIBezierPath()
    
            bullet.contentsScale = UIScreen.main.scale
    
            var bullets: [CGPoint] = []
            let width = coordinates.frame.width
            let height = coordinates.frame.height
    
            let widthBullets = CGFloat(width / 55)
            let heightBullets = CGFloat(height / 39)
    
            var hb: CGFloat?
            var wb: CGFloat?
    
            for n in 1...39 {
                hb = heightBullets * CGFloat(n)
                for o in 1...55 {
                    wb = widthBullets * CGFloat(o)
                    bullets.append(CGPoint(x: wb!, y: hb!))
                }
            }
    
            UIColor.black.setStroke()
    
            bullets.forEach { point in
                bulletPath.move(to: point)
                bulletPath.addLine(to: point)
            }
    
            bullet.path = bulletPath.cgPath
            bullet.opacity = 1.0
            bullet.lineWidth = 2.0
            bullet.lineCap = .round
            bullet.fillColor = UIColor.clear.cgColor
            bullet.strokeColor = bulletColor.cgColor
    
            if self.bullet == nil {
                self.bullet = bullet
                layer.addSublayer(bullet)
            }
    
            return layer
        }
    }
    
    以下是如何将其添加到BackgroundImageView:

    if eraser {
                //var rect: CGRect = CGRect()
                let linePath = UIBezierPath(rect: mainImageView.bounds)
    
                for (index, point) in line.enumerated() {
                    if index == 0 {
                        midPoint = CGPoint(
                            x: (point.x + point.x) / 2,
                            y: (point.y + point.y) / 2
                        )
                        //rect = CGRect(x: midPoint!.x, y: midPoint!.y, width: brush, height: brush)
                        linePath.move(to: midPoint!)
                    } else {
                        midPoint = CGPoint(
                            x: (point.x + line[index - 1].x) / 2,
                            y: (point.y + line[index - 1].y) / 2
                        )
                        //rect = CGRect(x: midPoint!.x, y: midPoint!.y, width: brush, height: brush)
                        linePath.addQuadCurve(to: midPoint!, controlPoint: line[index - 1])
                    }
                }
    
                let maskLayer = CAShapeLayer()
                maskLayer.lineWidth = brush
                maskLayer.lineCap = .round
                maskLayer.strokeColor = UIColor.clear.cgColor
                maskLayer.fillColor = UIColor.black.cgColor
                maskLayer.opacity = 1.0
                maskLayer.path = linePath.cgPath
                maskLayer.fillRule = .evenOdd
                mainImageView.layer.addSublayer(maskLayer)
                mainImageView.layer.mask = maskLayer
    
            }
    
    func updateTemplate() {
            let templates = TemplatePickerData()
            var loadLayer = templates.loadTemplateIds()
            if loadLayer.count == 0 {
                _ = templates.loadTemplates()
                loadLayer = templates.loadTemplateIds()
            }
            print("this is the template ID: \(templateId)")
            //let templateId = loadLayer[template].value(forKey: "templateId") as! Int
            if template < 0 {
                template = 0
            }
    
            switch template {
            case 0:
                //scrollView.image = UIImage(named: "habitTracker0")!
                scrollView.backgroundImageView.layer.sublayers?.removeAll()
                scrollView.backgroundImageView.layer.addSublayer(drawBullets.drawBullets(coordinates: scrollView.backgroundImageView, bulletColor: UIColor(red: 214.0/255.0, green: 214.0/255.0, blue: 214.0/255.0, alpha: 1.0)))
                scrollView.setNeedsLayout()
                scrollView.layoutIfNeeded()
                scrollView.setNeedsDisplay()
            case 1:
                //scrollView.image = UIImage(named: "monthTemplate0")!
                scrollView.backgroundImageView.layer.sublayers?.removeAll()
                scrollView.backgroundImageView.layer.addSublayer(drawNotes.drawLines(coordinates: scrollView.backgroundImageView, lineColor: UIColor(red: 214.0/255.0, green: 214.0/255.0, blue: 214.0/255.0, alpha: 1.0)))
                scrollView.setNeedsLayout()
                scrollView.layoutIfNeeded()
                scrollView.setNeedsDisplay()
            case 2:
                //scrollView.image = UIImage(named: "habitTracker0")!
                scrollView.backgroundImageView.layer.sublayers?.removeAll()
                scrollView.backgroundImageView.layer.addSublayer(drawNotes2.drawLines(coordinates: scrollView.backgroundImageView, lineColor: UIColor(red: 214.0/255.0, green: 214.0/255.0, blue: 214.0/255.0, alpha: 1.0)))
                scrollView.setNeedsLayout()
                scrollView.layoutIfNeeded()
                scrollView.setNeedsDisplay()
            default:
                if loadLayer.count > template {
                    template = 0
                }
                print("this layer is named: \(loadLayer[template].value(forKey: "templateName") as! String)")
                let layer = loadLayer[template].value(forKey: "templatePath") as! String
                templateId = loadLayer[template].value(forKey: "templateId") as! Int
                let thisTemplate = templates.loadImage(image: layer)
    
                scrollView.backgroundImageView.layer.sublayers?.removeAll()
                scrollView.backgroundImageView.layer.addSublayer(drawBullets.drawBullets(coordinates: scrollView.backgroundImageView, bulletColor: UIColor(red: 214.0/255.0, green: 214.0/255.0, blue: 214.0/255.0, alpha: 1.0)))
                scrollView.backgroundImageView.layer.addSublayer(thisTemplate)
                scrollView.setNeedsLayout()
                scrollView.layoutIfNeeded()
                scrollView.setNeedsDisplay()
            }
            scrollView.setNeedsDisplay()
    
            if optionsMenuView.pageNameTextField.text != "" {
                if isYear {
                    page = optionsMenuView.savePage(journalName: journalName, monthName: nil, weekName: nil, yearName: yearName, yearPosition: yearPosition, pageDrawingPath: pageDrawingPath, originalName: originalYearName, brushColor: 1, brushSize: brushSizeMenuView.brushSlider.value, templateId: templateId, pageDrawing: scrollView.mainImageView.layer)
                } else {
                    page = optionsMenuView.savePage(journalName: journalName, monthName: monthName, weekName: weekName, yearName: nil, yearPosition: nil, pageDrawingPath: pageDrawingPath, originalName: originalWeekName, brushColor: 1, brushSize: brushSizeMenuView.brushSlider.value, templateId: templateId, pageDrawing: scrollView.mainImageView.layer)
                }
            }
            optionsMenuView.templateId = templateId
        }
    
    func updateTemplate(){
    让templates=TemplatePickerData()
    var loadLayer=templates.loadTemplateId()
    如果loadLayer.count==0{
    _=模板。加载模板()
    loadLayer=templates.LoadTemplateId()
    }
    打印(“这是模板ID:\(templateId)”)
    //让templateId=loadLayer[template]。值(forKey:“templateId”)为!Int
    如果模板<0{
    模板=0
    }
    开关模板{
    案例0:
    //scrollView.image=UIImage(名为:“habitTracker0”)!
    scrollView.backgroundImageView.layer.sublayers?.removeAll()
    scrollView.backgroundImageView.layer.addSublayer(drawBullets.drawBullets(坐标:scrollView.backgroundImageView,bulletColor:UIColor(红色:214.0/255.0,绿色:214.0/255.0,蓝色:214.0/255.0,alpha:1.0)))
    scrollView.setNeedsLayout()
    scrollView.layoutIfNeeded()文件
    scrollView.setNeedsDisplay()
    案例1:
    //scrollView.image=UIImage(名为:“monthTemplate0”)!
    scrollView.backgroundImageView.layer.sublayers?.removeAll()
    scrollView.backgroundImageView.layer.addSublayer(drawNotes.drawLines(坐标:scrollView.backgroundImageView,线条颜色:UIColor(红色:214.0/255.0,绿色:214.0/255.0,蓝色:214.0/255.0,alpha:1.0)))
    scrollView.setNeedsLayout()
    scrollView.layoutIfNeeded()文件
    阴囊