使用 NSView 子类绘制 NSBezierPath 形状
Drawing an NSBezierPath Shape with NSView Subclass
我正在尝试在 NSView
canvas 上绘制使用 NSBezierPath
创建的形状。我创建了 NSView
.
的子类
// NSView //
import Cocoa
class DisplayView: NSView {
var path: NSBezierPath
var fillColor: NSColor
var strokeColor: NSColor
var weight: CGFloat
init(frame: CGRect, path: NSBezierPath, fillColor: NSColor, strokeColor: NSColor, weight: CGFloat){
self.path = path
self.fillColor = fillColor
self.strokeColor = strokeColor
self.weight = weight
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func draw(_ dirtyRect: NSRect) {
path.lineWidth = weight
fillColor.set()
path.fill()
strokeColor.set()
path.stroke()
}
}
// NSViewController //
import Cocoa
class ViewController: NSViewController {
// MARK: - IBOutlet
@IBOutlet weak var canvasView: NSView!
override func viewDidLoad() {
super.viewDidLoad()
override func viewDidLoad() {
super.viewDidLoad()
let path = Shapes.circle(maxSize: 100) // a path from a separate class
let rect = CGRect(x: 20, y: 20, width: 200, height: 200)
let pathView = DisplayView(frame: rect, path: path, fillColor: NSColor.green, strokeColor: NSColor.white, weight: 6.0)
canvasView.addSubview(pathView)
}
}
我得到以下结果。为什么边缘被两侧线宽的一半打破了?路径对象的大小仅为 100 pts x 100 pts。谢谢。
更新
下面是制作路径对象的代码
class Shapes {
static func circle(maxSize: CGFloat) -> NSBezierPath {
let oval = NSBezierPath.init(ovalIn: CGRect(x: 0.0 * maxSize, y: 0.0 * maxSize, width: 1.0 * maxSize, height: 1.0 * maxSize))
oval.close()
return oval
}
}
您已经创建了原点为 0,0 的贝塞尔曲线路径。结果,较粗的边框被渲染它的视图剪裁(您的 DisplayView
class)。
您需要创建路径,使原点为 (weight / 2 + 1)
而不是 0
。
或者您可以将平移变换应用于图形上下文并将原点移动 (weight / 2 + 1
。
override func draw(_ dirtyRect: NSRect) {
let ctx = NSGraphicsContext.current!.cgContext
ctx.saveGState()
let offset = weight / 2 + 1
ctx.translateBy(x: offset, y: offset)
path.lineWidth = weight
fillColor.set()
path.fill()
strokeColor.set()
path.stroke()
ctx.restoreGState()
}
我正在尝试在 NSView
canvas 上绘制使用 NSBezierPath
创建的形状。我创建了 NSView
.
// NSView //
import Cocoa
class DisplayView: NSView {
var path: NSBezierPath
var fillColor: NSColor
var strokeColor: NSColor
var weight: CGFloat
init(frame: CGRect, path: NSBezierPath, fillColor: NSColor, strokeColor: NSColor, weight: CGFloat){
self.path = path
self.fillColor = fillColor
self.strokeColor = strokeColor
self.weight = weight
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func draw(_ dirtyRect: NSRect) {
path.lineWidth = weight
fillColor.set()
path.fill()
strokeColor.set()
path.stroke()
}
}
// NSViewController //
import Cocoa
class ViewController: NSViewController {
// MARK: - IBOutlet
@IBOutlet weak var canvasView: NSView!
override func viewDidLoad() {
super.viewDidLoad()
override func viewDidLoad() {
super.viewDidLoad()
let path = Shapes.circle(maxSize: 100) // a path from a separate class
let rect = CGRect(x: 20, y: 20, width: 200, height: 200)
let pathView = DisplayView(frame: rect, path: path, fillColor: NSColor.green, strokeColor: NSColor.white, weight: 6.0)
canvasView.addSubview(pathView)
}
}
我得到以下结果。为什么边缘被两侧线宽的一半打破了?路径对象的大小仅为 100 pts x 100 pts。谢谢。
更新
下面是制作路径对象的代码
class Shapes {
static func circle(maxSize: CGFloat) -> NSBezierPath {
let oval = NSBezierPath.init(ovalIn: CGRect(x: 0.0 * maxSize, y: 0.0 * maxSize, width: 1.0 * maxSize, height: 1.0 * maxSize))
oval.close()
return oval
}
}
您已经创建了原点为 0,0 的贝塞尔曲线路径。结果,较粗的边框被渲染它的视图剪裁(您的 DisplayView
class)。
您需要创建路径,使原点为 (weight / 2 + 1)
而不是 0
。
或者您可以将平移变换应用于图形上下文并将原点移动 (weight / 2 + 1
。
override func draw(_ dirtyRect: NSRect) {
let ctx = NSGraphicsContext.current!.cgContext
ctx.saveGState()
let offset = weight / 2 + 1
ctx.translateBy(x: offset, y: offset)
path.lineWidth = weight
fillColor.set()
path.fill()
strokeColor.set()
path.stroke()
ctx.restoreGState()
}