首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >应该使用什么CALayer绘图( ctx:)坐标来用正确的比例尺绘制正确的点?

应该使用什么CALayer绘图( ctx:)坐标来用正确的比例尺绘制正确的点?
EN

Stack Overflow用户
提问于 2020-06-09 01:40:34
回答 1查看 204关注 0票数 0

我有一个NSView,它使用CALayers创建内容,并希望生成向量格式的pdf输出。首先,这是可能的,其次,苹果在文档中引用的逻辑坐标系是什么?最后,您应该如何绘制CALayers默认背景和边框属性?如果使用这些属性,则它们不会绘制到上下文中,如果绘制边框,则会重复属性设置。对于何时应该或不应该使用这些属性,或者在创建向量输出(例如pdf文档)时是否应该使用CALayers,这有点让人困惑。

视图有以下几个层:

视图层( sublayers

  • Sublayers
  • ),视图层(视图层)比绘图区域(
  • )大,包含图像的绘图层(
  • )和包含文本

的矢量绘图的

  • (视图层)。

下面列出了NSView类和CALayer子类。

视图层和绘图层被绘制在正确的位置,但是所有的绘图层子视图都绘制在错误的位置和错误的大小。

我假设这是因为绘图层有一个应用于is的转换,下面的绘图没有考虑到这一点。这就是问题所在吗?如果这是解决方案,我将如何将图层转换应用到CGContext,以使事情处于正确的位置?

代码语言:javascript
运行
复制
class DrawingView: NSView {

    override func draw(_ dirtyRect: NSRect) {
        super.draw(dirtyRect)
        guard let context = NSGraphicsContext.current?.cgContext else {
            return
        }
        // In theory should generate vector graphics
        self.layer?.draw(in: context)
        //Or
        // Generates bitmap image
        //self.layer?.render(in: context)
    }
}

class DrawingLayer: CALayer {

    override func draw(in ctx: CGContext) {
        drawBorder(in: ctx)
        if let subs = self.sublayers {
            for sub in subs {
                sub.draw(in: ctx)
            }
        }
    }
    func drawBorder(in ctx: CGContext){
        let rect = self.frame

        if let background = self.backgroundColor {
            ctx.setFillColor(background)
            ctx.fill(rect)
        }
        if let borders = self.borderColor {
            ctx.setStrokeColor(borders)
            ctx.setLineWidth(self.borderWidth)
            ctx.stroke(rect)
        }
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-09 22:39:04

以下是我的解决方案--使用不同的函数绘制PDF文件。我仍然不知道为什么系统在绘制到pdf和屏幕时的行为不一致。

编辑:-部分问题似乎是,我使用图层框架来计算绘图()函数中的大小/位置,但是当一个层被转换时,它的帧会改变大小和形状,以适应原来的旋转矩形!所以提示-保存你原来的矩形在其他地方,然后你的图纸不会突然变得奇怪,当你应用旋转或使用边界!!

EDIT2:-因此呈现(in:)工作,“有点”-一些3D转换被忽略,比如CATransform3DMakeTranslation()。幸运的是,旋转转换似乎可以工作,所以只需确保设置正确的原点,以避免需要转换。

当绘制pdf时,NSView的dirtyRect:)函数由CALayers way ( in:)函数调用,因此您似乎必须自己在层次结构上一直调用它们,记住要翻译每个子层的坐标系统--如果它们是在本地坐标系中绘制的话。请注意,这并不能保证pdf中的向量输出--似乎有些东西像文本被呈现为位图。如果有人对事情的行为和原因有解释,请解释。

无论如何,我只是回到使用CALayer.render( In :)函数,它会导致整个层层次结构被呈现--并且仍然使用一些向量和一些位映射元素!

代码语言:javascript
运行
复制
class DrawingView: NSView {

    var drawingLayer: DrawingLayer? {
        return self.layer?.sublayers?[0] as? DrawingLayer
    }

    override func draw(_ dirtyRect: NSRect) {
        //super.draw(dirtyRect)
        guard let context = NSGraphicsContext.current?.cgContext else {
            return
        }
        // In theory should generate vector graphics
        self.drawingLayer?.drawPdf(in: context)

        //Or
        // Generates bitmap image
        //self.layer?.render(in: context)
    }
}

class DrawingLayer: CALayer {

   var fillColor: CGColor?
   var lineColor: CGColor?
   var lineWidth: CGFloat = 0.5
    var scale: CGFloat = 1.0

    // No need for this since we don't need to call draw for each sublayer
    // that gets done for us!
    override func draw(in ctx: CGContext) {
        print("drawing DrawingLayer  \(name ?? "")")

//        if let subs = self.sublayers {
//            for sub in subs {
//                sub.draw(in: ctx)
//            }
//        }
    }
    func drawPdf(in ctx: CGContext) {


        ctx.saveGState()
        ctx.translateBy(x: self.frame.minX, y:  self.frame.minY)

       if let subs = self.sublayers {
           for sub in subs {

               (sub as! NormalLayer).drawPdf(in: ctx)
           }
       }

        ctx.restoreGState()
    }
}
class NormalLayer: CALayer {

    var fillColor: CGColor?
       var lineColor: CGColor?
       var lineWidth: CGFloat = 0.5
    var scale: CGFloat = 1.0

    override func draw(in ctx: CGContext) {
        drawBorder(in: ctx)
    }
    func drawBorder(in ctx: CGContext){
        let bds = self.bounds
        let rect = CGRect(x: bds.minX*scale, y: bds.minY*scale, width: bds.width*scale, height: bds.height*scale)
        print("drawing NormalLayer \(name ?? "")  \(rect)")

        if let background = self.fillColor {
            ctx.setFillColor(background)
            ctx.fill(rect)
        }
        if let borders = self.lineColor {
            ctx.setStrokeColor(borders)
            ctx.setLineWidth(self.lineWidth)
            ctx.stroke(rect)
        }
    }
    func drawPdf(in ctx: CGContext) {
        ctx.saveGState()
        ctx.translateBy(x: self.frame.minX, y:  self.frame.minY)
        drawBorder(in: ctx)
        ctx.restoreGState()
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62273702

复制
相关文章

相似问题

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