【问题标题】:Multiple pages view of the same PDF同一 PDF 的多页视图
【发布时间】:2016-10-25 18:46:21
【问题描述】:

我正在使用 PDFKit(swift 编程语言,macOS)中的 PDFView 来显示一些 PDF 文档。 我想显示同一个 PDF 的多个页面。 一种解决方案是从同一个 PDF 创建多个 PDFView,但这样我必须多次分配相同的内存,这对于图像丰富的 PDF 来说可能是个问题。 有没有什么快速的方法可以在 4/8 种不同的视图中显示同一 PDF 的不同页面?

编辑: @danielv 给这段代码带来的宝贵建议

import Cocoa
import Quartz

class PDFPageView: NSView {

    var pdfPage: PDFPage?

    override func draw(_ dirtyRect: NSRect) {
        super.draw(dirtyRect)
        if(pdfPage != nil) {
            let context = NSGraphicsContext.current()
            let pdfBox = PDFDisplayBox.mediaBox        
            let pdfBounds = pdfPage?.bounds(for: pdfBox)
            let scaleX = visibleRect.width/(pdfBounds?.width)!
            let scaleY = visibleRect.height/(pdfBounds?.height)!
            let scale = min(scaleX,scaleY)
            context?.cgContext.scaleBy(x: scale, y: scale)
            pdfPage?.draw(with: pdfBox, to: (context?.cgContext)!)
        }
    }
}

【问题讨论】:

  • “同一个 pdf 的多页”是什么意思? PDFView 已经使用滚动视图显示了多个页面,您要以不同的方式显示它们吗?
  • @danilev 最终我想做的是拥有一个“三重单页”,因此拥有三个关于同一个 PDF 的 PDFView,但我不想将使用的内存重复三倍。

标签: swift pdf macos-sierra


【解决方案1】:

PDFView很可能无法很好地用于显示同一 PDF 文档的多个页面。

但你可以自己做。 PDFPage 可以将自己绘制到任何给定的图形上下文中。您可以创建NSView 的子类来绘制页面或使用其他更精美的视图(如NSCollectionView)并将页面绘制到其行/列/网格。

以下是使用 NSView 的大致方法:

创建一个NSView的子类

class PDFPageView: NSView {

    var pdfPage: PDFPage?

    override func draw(_ dirtyRect: NSRect) {
        super.draw(dirtyRect)

        let context = NSGraphicsContext.current()!

        pdfPage?.draw(with: .mediaBox, to: context.cgContext)
    }
}

重要提示:您需要在绘制之前转换视图的上下文以适应页面并弥补任何页面旋转。 PDFPage 有一些辅助函数。

还要注意draw(with box: PDFDisplayBox, to context: CGContext)是从MacOS 10.12开始,要支持以前的版本使用draw(with box: PDFDisplayBox)

在您的控制器中,加载 PDF 文档并将每个页面分配给需要显示它的视图。

class ViewController: NSViewController {

    @IBOutlet weak var pdfPageView: PDFPageView?

    var pdfDocumenet: PDFDocument?

    override func viewDidLoad() {
        super.viewDidLoad()

        let url = URL(fileURLWithPath: "... pdf filename ...")
        pdfDocumenet = PDFDocument(url: url)

        pdfPageView?.pdfPage = pdfDocumenet?.page(at: 0)

    }
}

编辑(包括作者的 cmets):

当您尝试在 NSView 的上下文中绘制 PDF 页面时,页面绘制不尊重视图的边界。你自己试试,你就会明白我的意思。您需要自己进行上下文的缩放,通常是通过将当前图形上下文转换为所需的坐标。搜索 Cocoa Drawing Guide 以获取有关上下文和转换的详细信息。 PDFPage 提供了一些帮助方法,让您可以获取原始页面边界以及页面可能用于旋转页面的转换(如果需要)。

要获取页面的矩形,您使用边界(对于框:PDFDisplayBox),而不是上下文大小。您需要先转换上下文,然后再使用它。但这都在文档中,您确实需要阅读 Cocoa/Quartz 绘图指南和 PDF 页面的文档。所以一定要去那里看看。

【讨论】:

  • 谢谢!您能否更好地解释一下“重要:您将……为此发挥作用”这句话。我不明白问题是什么。
  • 当您尝试在 NSView 的上下文中绘制 PDF 页面时,页面绘制不尊重视图的边界。你自己试试,你就会明白我的意思。您需要自己进行上下文的缩放,通常是通过将当前图形上下文转换为所需的坐标。搜索 Cocoa 绘图指南 以获取有关上下文和转换的详细信息。 PDFPage 提供了一些帮助方法,让您获取原始页面边界以及页面可能用于旋转页面的转换(如果需要)。
  • 我已经尝试过,但它不起作用(抱歉格式错误)let context = NSGraphicsContext.current() pdfPage?.draw(with: .mediaBox, to: context!.cgContext) var pdfWidth = (context?.cgContext.width)! var pdfHeight = (context?.cgContext.height)! var scaleX = visibleRect.width/CGFloat(pdfWidth) var scaleY = visibleRect.height/CGFloat(pdfHeight) context?.cgContext.scaleBy(x: scaleX, y: scaleY) 我认为更好的选择(如果代码有效)是在“不可见的绘图上下文”中绘制和真正的。
  • 什么不起作用?图纸?缩放?要获取页面的矩形,请使用bounds(for box: PDFDisplayBox),而不是上下文大小。您需要在绘制上下文之前对其进行转换。但这一切都在文档中,您确实需要阅读 Cocoa/Quartz 绘图指南和 PDF 页面的文档...
  • 我想我已经找到了方法。我将发布我的(希望如此)工作代码。
猜你喜欢
  • 1970-01-01
  • 2013-07-30
  • 2013-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-18
相关资源
最近更新 更多