同一 PDF 的多页视图
Multiple pages view of the same PDF
我正在使用 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)!)
}
}
}
PDFView
很可能无法很好地显示同一 PDF 文档的多个页面。
但是你可以自己做。 PDFPage
可以将自己绘制到任何给定的图形上下文。您可以创建 NSView
的子类来绘制页面或使用其他更花哨的视图,例如 NSCollectionView
并将页面绘制到其 rows/columns/grid.
以下是使用 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)
}
}
编辑(包括作者的评论):
当您尝试在 NSView 的上下文中绘制 PDF 页面时,页面绘制不遵守视图的边界。自己试试吧,你会明白我的意思。您需要自己对上下文进行缩放,通常是将当前图形上下文转换为所需的坐标。搜索 Cocoa 绘图指南以获取有关上下文和转换的详细信息。 PDFPage 提供了一些辅助方法,让您获得原始页面边界和页面可能用于旋转页面的转换(如果需要)。
要获取页面的矩形,您可以使用边界(对于框:PDFDisplayBox),而不是上下文大小。在使用它之前,您需要转换上下文。但这都在文档中,您确实需要阅读 Cocoa/Quartz 绘图指南和 PDF 页面的文档。所以一定要去那里看看。
我正在使用 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)!)
}
}
}
PDFView
很可能无法很好地显示同一 PDF 文档的多个页面。
但是你可以自己做。 PDFPage
可以将自己绘制到任何给定的图形上下文。您可以创建 NSView
的子类来绘制页面或使用其他更花哨的视图,例如 NSCollectionView
并将页面绘制到其 rows/columns/grid.
以下是使用 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)
}
}
编辑(包括作者的评论):
当您尝试在 NSView 的上下文中绘制 PDF 页面时,页面绘制不遵守视图的边界。自己试试吧,你会明白我的意思。您需要自己对上下文进行缩放,通常是将当前图形上下文转换为所需的坐标。搜索 Cocoa 绘图指南以获取有关上下文和转换的详细信息。 PDFPage 提供了一些辅助方法,让您获得原始页面边界和页面可能用于旋转页面的转换(如果需要)。
要获取页面的矩形,您可以使用边界(对于框:PDFDisplayBox),而不是上下文大小。在使用它之前,您需要转换上下文。但这都在文档中,您确实需要阅读 Cocoa/Quartz 绘图指南和 PDF 页面的文档。所以一定要去那里看看。