Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 使用NSBezierPath绘制点_Swift_Cocoa_Nsbezierpath - Fatal编程技术网

Swift 使用NSBezierPath绘制点

Swift 使用NSBezierPath绘制点,swift,cocoa,nsbezierpath,Swift,Cocoa,Nsbezierpath,我想创建一个单像素大小的点。我假设这样做的方法是使用NSBezierPath绘制一条线,起点等于终点(请参见下面的代码),但这样做会使窗口完全变空 func drawPoint() { let path = NSBezierPath() NSColor.blue.set() let fromPoint = NSMakePoint(CGFloat(100) , CGFloat(100)) let toPoint = NSMakePoint(CGFloat(100)

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

func drawPoint() {
    let path = NSBezierPath()
    NSColor.blue.set()
    let fromPoint = NSMakePoint(CGFloat(100) , CGFloat(100))
    let toPoint = NSMakePoint(CGFloat(100) , CGFloat(100))
    path.move(to: fromPoint)
    path.line(to: toPoint)
    path.lineWidth = 1.0
    path.stroke()
    path.fill()
}
但是,如果我将toPoint坐标从100100更改为101101(或100100以外的任何一组坐标),将显示一个蓝色形状。有人知道为什么会这样吗

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


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

您有几个问题:

我想创建一个单像素大小的点

你确定吗?如果你在视网膜显示器上呢?如果您正在绘制PDF文件,并将在600 dpi激光打印机上打印,该怎么办

我假设这样做的方法是使用NSBezierPath绘制一条起点等于终点的线

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

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

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

  • 在视网膜屏幕上,整数和半整数坐标默认位于像素的边缘,而不是像素的中心。沿整数或半整数坐标的笔划跨越像素之间的边界。当
    lineWidth=1.0时,两侧的像素完全填满。如果只想填充单个像素,则需要使用以
    .25
    .75
    结尾的坐标和
    线宽
    0.5
    坐标

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

这只能在非视网膜屏幕上显示“单个像素大小的点”(或者如果缩放图形上下文)。如果你真的想在视网膜屏幕上显示一个像素点,你需要调整它。但你最好坚持点而不是像素

综上所述,以下是如何创建并笔划
NSBezierPath
以填充一个像素:

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()
 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()
结果:

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

func dotImage2() -> 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 {

        NSColor.blue.set()
        CGRect(x: 10, y: 10, width: 1, height: 1).fill()

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

let image2 = dotImage2()
结果:


您有几个问题:

我想创建一个单像素大小的点

你确定吗?如果你在视网膜显示器上呢?如果您正在绘制PDF文件,并将在600 dpi激光打印机上打印,该怎么办

我假设这样做的方法是使用NSBezierPath绘制一条起点等于终点的线

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

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

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

  • 在视网膜屏幕上,整数和半整数坐标默认位于像素的边缘,而不是像素的中心。沿整数或半整数坐标的笔划跨越像素之间的边界。当
    lineWidth=1.0时,两侧的像素完全填满。如果只想填充单个像素,则需要使用以
    .25
    .75
    结尾的坐标和
    线宽
    0.5
    坐标

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

这只能在非视网膜屏幕上显示“单个像素大小的点”(或者如果缩放图形上下文)。如果你真的想在视网膜屏幕上显示一个像素点,你需要调整它。但你最好坚持点而不是像素

综上所述,以下是如何创建并笔划
NSBezierPath
以填充一个像素:

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()
 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()
结果:

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

func dotImage2() -> 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 {

        NSColor.blue.set()
        CGRect(x: 10, y: 10, width: 1, height: 1).fill()

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

let image2 = dotImage2()
结果:


在rob mayoff的解决方案之上,我使用NSGraphicsContext找到了一个不同的解决方案。我刚刚抓取了核心图形上下文并关闭了抗锯齿功能(见下文)

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

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()
 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的值,可以在rob mayoff的基础上得到正好一个像素的阴影。