使用NSView子类绘制NSBezierPath形状

时间:2018-06-02 04:47:39

标签: swift cocoa nsview nsbezierpath

我尝试在NSBezierPath画布上绘制使用NSView创建的形状。我创建了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。感谢。

enter image description here

更新

以下是制作路径对象的代码。

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
    }
}

1 个答案:

答案 0 :(得分:2)

您已创建原点为0,0的贝塞尔曲线路径。因此,较厚的边框会被(DisplayView类)中呈现的视图剪切。

您需要创建路径,因此原点为(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()
}