UIMarkupTextPrintFormatter 创建具有自定义背景和透明 HTML 内容的 PDF

Posted

技术标签:

【中文标题】UIMarkupTextPrintFormatter 创建具有自定义背景和透明 HTML 内容的 PDF【英文标题】:UIMarkupTextPrintFormatter PDF creation with custom background and transparent HTML content 【发布时间】:2017-10-03 14:15:13 【问题描述】:

我正在使用UIPrintPageRendererUIMarkupTextPrintFormatter 来打印在UIWebView 中呈现的html 页面。我正在努力实现以下目标: 我想将 html 内容作为透明层渲染到上下文中,但是当在上下文中使用 UIPrintPageRenderer 渲染覆盖下面的所有内容时,html 内容的背景颜色始终为白色。

html样式包含如下代码sn-p:

body 
      background-color: transparent !important;;
      -webkit-print-color-adjust: exact;

UIWebView中我可以看到html的背景确实是透明的,因为我将UIWebView的背景设置为不同的颜色。

这是我用于创建 PDF 数据的代码:

let printPageRenderer = UIPrintPageRenderer()
let printFormatter = UIMarkupTextPrintFormatter(markupText: htmlContent)
printPageRenderer.addPrintFormatter(printFormatter, startingAtPageAt: 0)

let data = NSMutableData()
UIGraphicsBeginPDFContextToData(data, Constants.Pdf.rect, nil)
let context = UIGraphicsGetCurrentContext()!

for i in 0..<printPageRenderer.numberOfPages 
    UIGraphicsBeginPDFPage()

    let backCoverView = UIView(frame: Constants.Pdf.rect)
    backCoverView.backgroundColor = UIColor(patternImage: UIImage(named: "background.png")!)
    backCoverView.layer.render(in: context)

    context.clear(printableRect)

    printPageRenderer.setValue(NSValue(cgRect: printableRect), forKey: "printableRect")
    printPageRenderer.drawPage(at: i, in: UIGraphicsGetPDFContextBounds())


UIGraphicsEndPDFContext()

我的问题是在“background.png”上呈现的 html 内容不是透明的,而是具有白色背景。 html 样式中的 transparent 属性似乎被UIPrintPageRenderer 忽略了。将 html 样式中的 background-color 设置为例如blue 将渲染的 html 背景颜色从白色更改为蓝色。我还尝试通过使用 context.clear(printableRect) 使上下文透明来使呈现的 html 透明,但无济于事。

如何让UIPrintPageRenderer 打印具有透明背景的 html 内容,以便上下文中已经呈现的背景不会被 html 的白色背景覆盖?

【问题讨论】:

我没有用过 UIPrintPageRenderer,但我用过 TCPDF(一个类似的 PDF 生成器),而且 TCPDF 只支持 HTML 4,如果我没记错的话,它不支持透明度。 【参考方案1】:

这不是保证,但正如 Yvonne 所说,您的 PDF 渲染器可能不支持 transparent 作为颜色值。

可能的解决方案 A

尝试创建一个只有一个 100% 透明像素的 1px x 1px PNG 图像,然后将其设置为元素上的重复背景图像。

可能的解决方案 B

当这个库呈现 HTML 元素时,它本身可能是白色的。您可以将 CSS 应用到 html 标记,就像使用 body 一样。

可能的解决方案 C

如果我正确理解您的情况,您正在尝试将 UIWebView 内的渲染 PDF 覆盖在其他应用内内容之上。我无法谈论 PDF 是否真的可以支持透明度。 UIWebView 可能需要自己的属性(更不用说可能有一个默认背景为白色的 PDF 查看器)。如果您可以控制 UIWebView 的样式,请查看:How to make a transparent UIWebView

可能的解决方案 D

也许使用 Canvas(HTML 或 Switft)来呈现图像而不是 PDF 会更好。如果这适用于您的用例,那么从长远来看,它可能是一个更好的选择。

【讨论】:

感谢您的回答!我尝试了解决方案 A 和 B,但它们不起作用。我们已经尝试了解决方案 C 无济于事。解决方案 D 目前在我们的项目中不是一个选项。关于解决方案 C:在创建 pdf 之前,我们在 UIWebView 中显示 html 页面,然后在完全呈现之后,我们将 html 字符串传递给 UIMarkupTextPrintFormatter 并构建 pdf。在将 html 页面渲染为 pdf 之前,我们为每个页面设置了整个 pdf 页面的背景。在 web 视图和浏览器测试中,我们可以清楚地看到 html 页面是透明的。 因此您可以使用包含具有透明背景的 HTML 的 Web 视图覆盖您的应用内容,是吗? PDF 是否提供进一步的实用程序,而不是仅仅覆盖用于呈现 PDF 的 HTML?我问是因为使用这些库渲染透明 PDF 可能不可行。如果可能有其他解决方案,则可能值得追求该解决方案。 pdf 的目的是我们首先在其上绘制图像(背景),然后在其上绘制应该是透明的 html,因此上下文中已经插入的底层背景应该可以通过的HTML。目前我们不可能/不可行在 html 本身中绘制/插入背景。【参考方案2】:

通过切换到不同的UIPrintFormatter 解决了问题。从UIMarkupTextPrintFormatter 切换到UIViewPrintFormatter,它尊重透明度。

【讨论】:

以上是关于UIMarkupTextPrintFormatter 创建具有自定义背景和透明 HTML 内容的 PDF的主要内容,如果未能解决你的问题,请参考以下文章