首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用NSBezierPath绘制点

使用NSBezierPath绘制点
EN

Stack Overflow用户
提问于 2018-09-01 15:03:15
回答 3查看 873关注 0票数 1

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

代码语言:javascript
复制
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坐标从100,100更改为101,101 (或100,100以外的任何一组坐标),就会出现一个蓝色的形状。有人知道为什么会这样吗?

我发现的另一个问题是,如果你让托普林的坐标相当于101,101,那么它就会创建一个长度为两个像素的正方形,但也会添加另一个像素长的模糊层(见下图,放大以获得详细信息)。

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

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-09-01 20:20:29

你有一些问题:

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

真的吗?如果你在Retina显示器上呢?如果您正在绘制的PDF将打印在600 dpi激光打印机上?

我认为这样做的方法是使用NSBezierPath绘制一条与终点相等的起始点。

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

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

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

  • 在非Retina屏幕上,整数坐标默认位于像素边缘,而不是像素中心。沿整数坐标的笔画跨越像素之间的边界,因此(使用lineWidth = 1.0)可以得到多个部分填充的像素。要填充单个像素,需要使用以.5 (像素中心)结尾的坐标。
  • 在Retina屏幕上,整数和半整数坐标默认位于像素的边缘,而不是像素的中心。沿整数或半整数坐标的笔画跨越像素之间的边界.使用lineWidth = 1.0,两边的像素都被完全填充。如果您只想填充一个像素,则需要使用以.25.75lineWidth of 0.5结尾的坐标。
  • 在非缩放的PDF上下文中,lineWidth of 1.0名义上对应于1/72英寸,填充像素的数量取决于输出设备。

path.lineWidth = 1.0

这只能在非Retina屏幕上给出“一个像素大小的点”(或者缩放图形上下文)。如果您真的希望在Retina屏幕上有一个像素点,则需要调整它。但你最好还是坚持点而不是像素。

尽管如此,以下是如何创建和绘制一个NSBezierPath以填充一个像素:

代码语言:javascript
复制
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()

结果:

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

代码语言:javascript
复制
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()

结果:

票数 5
EN

Stack Overflow用户

发布于 2018-09-01 22:37:50

在罗布·梅奥夫的解决方案之上,我用NSGraphicsContext找出了一个不同的解决方案。我只是抓住核心图形上下文,并关闭了反走样(见下文)

代码语言:javascript
复制
 let context = NSGraphicsContext.current?.cgContext
 context?.setShouldAntialias(false)

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

代码语言:javascript
复制
 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的值,您可以得到一个像素阴影。

票数 0
EN

Stack Overflow用户

发布于 2018-09-04 21:48:17

在: x,y的大小:宽度,高度处画一个点。

代码语言:javascript
复制
NSBezierPath(ovalIn: CGRect(x: 5.5, y: 5.5, width: 4.0, height: 4.0)).fill()

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52129360

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档