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