使用NSBezierPath绘制点

时间:2018-09-01 15:03:16

标签: swift cocoa nsbezierpath

我想创建一个像素大小的点。我以为这样做的方法是使用NSBezierPath绘制一条起点等于终点的线(请参见下面的代码),但这样做会形成一个完全空白的窗口。

var lp = pzscore(z);
document.getElementById('lp').value = lp.toFixed(4);
var rp = 1 - lp;
document.getElementById('rp').value = rp.toFixed(4);
 var tp = 2 * rp;
document.getElementById('tp').value = tp.toFixed(4);
 var cl = 1 - tp;
document.getElementById('cl').value = cl.toFixed(4);

但是,如果将toPoint坐标从100,100更改为101,101(或除100,100以外的任何其他坐标集),则会显示蓝色。有人知道为什么会这样吗?

我发现的另一个问题是,如果将toPoint的坐标设为(例如)101,101,那么它将创建一个具有两个像素长度的正方形,但还会添加另一个像素长度的模糊层(请参见下图,放大以获取详细信息)。

pictureOfSquare

但是,我想做的只是将一个小的蓝色正方形放到一个像素的大小上,而没有模糊。有人知道我该怎么做吗?

3 个答案:

答案 0 :(得分:3)

您遇到一些问题:

  

我要创建一个像素大小的点。

确定吗?如果您在Retina显示器上怎么办?如果要绘制将要在600 dpi激光打印机上打印的PDF,该怎么办?

  

我认为这样做的方法是使用NSBezierPath画一条线,起点等于终点

这是一种绘制lineWidth大小的点的方法,如果lineCap属性设置为.round.square。默认的lineCap.butt,这将导致一个空笔触。如果将lineCap设置为.round.square,则会得到非空笔划。

let fromPoint = NSMakePoint(CGFloat(100) , CGFloat(100))
let toPoint = NSMakePoint(CGFloat(100) , CGFloat(100))
path.move(to: fromPoint)
path.line(to: toPoint)

您需要了解坐标网格与像素的关系:

  • 在非视网膜屏幕上,默认情况下,整数坐标位于像素的边缘,而不是像素的中心。沿整数坐标的笔划跨越像素之间的边界,因此(使用lineWidth = 1.0)会得到多个部分填充的像素。要填充单个像素,您需要使用以.5(像素的中心)结尾的坐标。

  • 在Retina屏幕上,默认情况下,整数和半整数坐标位于像素边缘,而不是像素中心。沿整数或半整数坐标的笔划跨越像素之间的边界。使用lineWidth = 1.0,可以完全填充两侧的像素。如果只想填充单个像素,则需要使用以.25.75结尾的坐标和lineWidth的{​​{1}}。

  • 在未缩放的PDF上下文中,0.5中的lineWidth名义上对应于1/72英寸,并且填充像素的数量取决于输出设备。

1.0

这只能在非Retina屏幕上(或缩放图形上下文)为您提供“单个像素大小的点”。如果您确实要在Retina屏幕上单个像素点,则需要对其进行调整。但是最好不要紧贴点而不是像素。

所有说明,这是创建和描画path.lineWidth = 1.0 以填充一个像素的方法:

NSBezierPath

结果:

dot image

但是,您可能更喜欢直接直接填充矩形:

import AppKit

func dotImage() -> CGImage {
    let gc = CGContext(data: nil, width: 20, height: 20, bitsPerComponent: 8, bytesPerRow: 0, space: CGColorSpace(name: CGColorSpace.sRGB)!, bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue)!
    let nsGc = NSGraphicsContext(cgContext: gc, flipped: false)
    NSGraphicsContext.current = nsGc; do {

        let path = NSBezierPath()
        path.move(to: .init(x: 10.5, y: 10.5))
        path.line(to: .init(x: 10.5, y: 10.5))
        path.lineWidth = 1
        path.lineCapStyle = .round
        NSColor.blue.set()
        path.stroke()

    }; NSGraphicsContext.current = nil
    return gc.makeImage()!
}

let image = dotImage()

结果:

dot image 2

答案 1 :(得分:0)

除了rob mayoff的解决方案之外,我还找到了另一个使用NSGraphicsContext的解决方案。我只是抓住了Core Graphics上下文并关闭了抗锯齿功能(见下文)

 let context = NSGraphicsContext.current?.cgContext
 context?.setShouldAntialias(false)

然后,我创建了一个像素大小的路径:

 context.setLineWidth(0.5)
 context.setStrokeColor(color)
 context.beginPath()
 context.move(to: CGPoint(x: 100, y: 100))
 context.addLine(to: CGPoint(x: 100.15, y: 100.15))
 context.strokePath()

在向该行添加端点时,我注意到,通过为其赋予一个大于100但小于100.5的值,可以得到一个阴影像素。

答案 2 :(得分:0)

在以下位置绘制点:x,y,尺寸:宽度,高度。

NSBezierPath(ovalIn: CGRect(x: 5.5, y: 5.5, width: 4.0, height: 4.0)).fill()

要微调“像素”的位置和大小,请在DoubleCGFloat参数中使用小数。