Calayer绘制在视图之外
我有使用此代码使用此代码:
import UIKit
class Page: UIView {
var bezierMemory = [BezierRecord]()
var currentBezier: UIBezierPath = UIBezierPath()
var firstPoint: CGPoint = CGPoint()
var previousPoint: CGPoint = CGPoint()
var morePreviousPoint: CGPoint = CGPoint()
var previousCALayer: CALayer = CALayer()
var pointCounter = 0
var selectedPen: Pen = Pen(width: 3.0, strokeOpacity: 1, strokeColor: .red, fillColor: .init(gray: 0, alpha: 0.5), isPencil: true, connectsToStart: true, fillPencil: true)
enum StandardPageSizes {
case A4, LEGAL, LETTER
}
var firstCALayer = true
var pointsTotal = 0
override init(frame: CGRect) {
super.init(frame: .zero)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
guard let touch = touches.first else { return }
let point = touch.location(in: self)
firstPoint = point
pointCounter = 1
currentBezier = UIBezierPath()
currentBezier.lineWidth = selectedPen.width
selectedPen.getStroke().setStroke()
currentBezier.move(to: point)
previousPoint = point
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesMoved(touches, with: event)
guard let touch = touches.first else { return }
let point = touch.location(in: self)
pointCounter += 1
if (pointCounter == 3) {
let midpoint = CGPoint(x: (morePreviousPoint.x + point.x)/2.0, y: (morePreviousPoint.y + point.y)/2.0)
currentBezier.addQuadCurve(to: midpoint, controlPoint: morePreviousPoint)
let updatedCALayer = CAShapeLayer()
updatedCALayer.path = currentBezier.cgPath
updatedCALayer.lineWidth = selectedPen.width
updatedCALayer.opacity = selectedPen.strokeOpacity
updatedCALayer.strokeColor = selectedPen.getStroke().cgColor
updatedCALayer.fillColor = selectedPen.getFill()
if (firstCALayer) {
layer.addSublayer(updatedCALayer)
firstCALayer = false
} else {
layer.replaceSublayer(previousCALayer, with: updatedCALayer)
}
previousCALayer = updatedCALayer
pointCounter = 1
}
morePreviousPoint = previousPoint
previousPoint = point
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesEnded(touches, with: event)
guard let touch = touches.first else { return }
let point = touch.location(in: self)
if (pointCounter != 3) {
if (selectedPen.connectsToStart) {
currentBezier.addQuadCurve(to: firstPoint, controlPoint: previousPoint)
} else {
currentBezier.addQuadCurve(to: point, controlPoint: previousPoint)
}
let updatedCALayer = CAShapeLayer()
updatedCALayer.path = currentBezier.cgPath
updatedCALayer.lineWidth = selectedPen.width
updatedCALayer.opacity = selectedPen.strokeOpacity
updatedCALayer.strokeColor = selectedPen.getStroke().cgColor
updatedCALayer.fillColor = selectedPen.getFill()
if (firstCALayer) {
layer.addSublayer(updatedCALayer)
firstCALayer = false
} else {
// layer.setNeedsDisplay()
layer.replaceSublayer(previousCALayer, with: updatedCALayer)
}
}
firstCALayer = true
let bezierRecord = BezierRecord(bezier: currentBezier, strokeColor: selectedPen.getStroke(), fillColor: selectedPen.getFill(), strokeWidth: selectedPen.width)
bezierMemory.append(bezierRecord)
}
private func normPoint(point: CGPoint) -> CGPoint {
return CGPoint(x: point.x/frame.width, y: point.y/frame.height)
}
public class BezierRecord {
var bezier: UIBezierPath
var strokeColor: UIColor
var strokeWidth: CGFloat
var fillColor: CGColor
init(bezier: UIBezierPath, strokeColor: UIColor, fillColor: CGColor, strokeWidth: CGFloat) {
self.bezier = bezier
self.strokeColor = strokeColor
self.strokeWidth = strokeWidth
self.fillColor = fillColor
}
}
}
真的,唯一的相关部分是触摸并触摸的,在Calayer's的地方处理。从GIF中可以看到,只要我开始在边界内绘制,我就可以在页面(Uiview)的边界之外绘制。我不想要这个 - 我想要的是您可以在页面范围之外保持中风(只要您在页面上启动),但是中风不会出现在页面外。有什么想法吗?
编辑:我应该补充一点,对于这些UibezierCurves,(0,0)被认为是页面左上角(白色),而不是整个视图。因此,例如,从页面上开始并继续开启的Beziers是负面的。
I have this behaviour with this code:
import UIKit
class Page: UIView {
var bezierMemory = [BezierRecord]()
var currentBezier: UIBezierPath = UIBezierPath()
var firstPoint: CGPoint = CGPoint()
var previousPoint: CGPoint = CGPoint()
var morePreviousPoint: CGPoint = CGPoint()
var previousCALayer: CALayer = CALayer()
var pointCounter = 0
var selectedPen: Pen = Pen(width: 3.0, strokeOpacity: 1, strokeColor: .red, fillColor: .init(gray: 0, alpha: 0.5), isPencil: true, connectsToStart: true, fillPencil: true)
enum StandardPageSizes {
case A4, LEGAL, LETTER
}
var firstCALayer = true
var pointsTotal = 0
override init(frame: CGRect) {
super.init(frame: .zero)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
guard let touch = touches.first else { return }
let point = touch.location(in: self)
firstPoint = point
pointCounter = 1
currentBezier = UIBezierPath()
currentBezier.lineWidth = selectedPen.width
selectedPen.getStroke().setStroke()
currentBezier.move(to: point)
previousPoint = point
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesMoved(touches, with: event)
guard let touch = touches.first else { return }
let point = touch.location(in: self)
pointCounter += 1
if (pointCounter == 3) {
let midpoint = CGPoint(x: (morePreviousPoint.x + point.x)/2.0, y: (morePreviousPoint.y + point.y)/2.0)
currentBezier.addQuadCurve(to: midpoint, controlPoint: morePreviousPoint)
let updatedCALayer = CAShapeLayer()
updatedCALayer.path = currentBezier.cgPath
updatedCALayer.lineWidth = selectedPen.width
updatedCALayer.opacity = selectedPen.strokeOpacity
updatedCALayer.strokeColor = selectedPen.getStroke().cgColor
updatedCALayer.fillColor = selectedPen.getFill()
if (firstCALayer) {
layer.addSublayer(updatedCALayer)
firstCALayer = false
} else {
layer.replaceSublayer(previousCALayer, with: updatedCALayer)
}
previousCALayer = updatedCALayer
pointCounter = 1
}
morePreviousPoint = previousPoint
previousPoint = point
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesEnded(touches, with: event)
guard let touch = touches.first else { return }
let point = touch.location(in: self)
if (pointCounter != 3) {
if (selectedPen.connectsToStart) {
currentBezier.addQuadCurve(to: firstPoint, controlPoint: previousPoint)
} else {
currentBezier.addQuadCurve(to: point, controlPoint: previousPoint)
}
let updatedCALayer = CAShapeLayer()
updatedCALayer.path = currentBezier.cgPath
updatedCALayer.lineWidth = selectedPen.width
updatedCALayer.opacity = selectedPen.strokeOpacity
updatedCALayer.strokeColor = selectedPen.getStroke().cgColor
updatedCALayer.fillColor = selectedPen.getFill()
if (firstCALayer) {
layer.addSublayer(updatedCALayer)
firstCALayer = false
} else {
// layer.setNeedsDisplay()
layer.replaceSublayer(previousCALayer, with: updatedCALayer)
}
}
firstCALayer = true
let bezierRecord = BezierRecord(bezier: currentBezier, strokeColor: selectedPen.getStroke(), fillColor: selectedPen.getFill(), strokeWidth: selectedPen.width)
bezierMemory.append(bezierRecord)
}
private func normPoint(point: CGPoint) -> CGPoint {
return CGPoint(x: point.x/frame.width, y: point.y/frame.height)
}
public class BezierRecord {
var bezier: UIBezierPath
var strokeColor: UIColor
var strokeWidth: CGFloat
var fillColor: CGColor
init(bezier: UIBezierPath, strokeColor: UIColor, fillColor: CGColor, strokeWidth: CGFloat) {
self.bezier = bezier
self.strokeColor = strokeColor
self.strokeWidth = strokeWidth
self.fillColor = fillColor
}
}
}
Really the only relevant parts are touchesMoved and touchesEnded, where CALayer's are dealt with. As you can see from the gif, I can draw outside the bounds of the Page (UIView) as long as I start drawing inside the bounds. I do not want this - what I would like is something where you can maintain a stroke outside of the bounds of the Page (as long as you start it on the Page), but the stroke wont appear outside of the Page. Any ideas?
EDIT: I should add that for these UIBezierCurves, (0, 0) is considered to be the top left of the Page (white), and not the entire view. Thus, for example, beziers that start on the page and continue on, are negative.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您需要做的就是在视图上设置
.clipstobounds = true
。一种方法:
您可以 put
self.clipstobounds = true
在两个init
funcs中添加这样的“常见初始化”功能(无论如何,它都可以命名为...这就是我的做法)。通常,我们有其他需要调用的“初始设置”代码,这避免了复制代码。All you should need to do is set
.clipsToBounds = true
on the view.One approach:
You could put
self.clipsToBounds = true
in both of theinit
funcs, but it is common practice (no pun intended) to add a "common init" func like this (it can be named whatever... this is how I do it). Frequently we have other "initial setup" code that we want called, and this avoids duplicating the code.