我有一个包含大量列的大表,我需要使用DOMPDF将其放入PDF页面。就像here一样,我的标题比相应的内容宽得多,所以我试图旋转它们。在Firefox中打开的HTML似乎没问题,但生成的PDF不是。
HTML :
<td class="cell rotated_vertical_td" style="width:3%;">
<div class="rotated_vertical">Rotated_</div>
</td>
上面的width属性是根据列总数在PHP中计算的。
CSS :
.cell {
font-size: 8pt;
}
.rotated_vertical_td {
height: 280px;
width: 20px;
text-transform:uppercase;
margin:0;
padding:0;
}
.rotated_vertical {
-webkit-transform:rotate(270deg);
-moz-transform:rotate(270deg);
-ms-transform:rotate(270deg);
-o-transform:rotate(270deg);
transform:rotate(270deg);
transform-origin: 50%;
width: 20px;
}
我必须将.cell
类应用于每个<td>
,因为DOMPDF由于某种原因未获取table td
规则。
似乎像DOMPDF首先渲染文本,相应地更改表格单元格,然后旋转它。这意味着该列仍然占用了相当多的空间并且打破了整个点。
我已尝试使用substr()
将文字剪切为仅2,4或8个字符。看起来列宽正在相应调整。
这些是正在呈现的实际PDF的屏幕截图。正如您所看到的,即使标记和CSS相同,最后一列也适合较少的列。唯一改变的是字符数。看起来它完全忽略了我在这些标题上设置的宽度。
对于HTML,看起来内部div上的width: 20px;
会有所不同 - 如果我删除它,HTML标题也会变宽。
再次,看起来内部div宽度拉伸表头单元格。我可以覆盖该宽度,它适用于HTML,但它不适用于PDF。
更糟糕的是DOMPDF does not seem to support having multiple page orientations in a single document因此我无法在横向模式中使用该页面。
在对this question的回答中,建议使用绝对定位,但我不确定它是如何与DOMPDF一起使用的。例如,他们将position:fixed
元素视为页眉,可能会为绝对定位元素保留一些内容。
请帮忙
感谢 BrianS 的帮助,我设法使用他建议的CSS方法和从GitHub下载的最新DOMPDF来使文本轮换。在此之前,我正在为每个标题生成带有旋转文本的动态图像。
我想为那些到处寻找解决方案的人指出一些事情(包括未来的我猜)
定位内容是一场噩梦。似乎没有办法可预测地控制旋转标题的位置和行为,既不在Firefox中,也不在DOMPDF中,并且 令人沮丧。首先,我必须将transform-origin
属性更改为:
transform-origin: left bottom 0;
...只是因为它的位置不那么随机,因为否则 <{em> top
/ left
或 {{1} } / width
属性保持在两个维度中移动块。事实上有大约7个变量可以控制height
元素的top
,left
,width
/ height
以及{{1和包裹单元格的:after
/ line-height
使得无法通过所有可能的组合来获得理想的位置。
如果标题太长并且包含任何易碎字符(例如空格),则会将其拆分为多行,并通过相互叠加将这些行合并为一行。请参阅:
我无法找到预防这种情况的方法。看到不包含任何易碎字符的文本仍然放在一行上,
width
属性中的height
替换空格,但是直接打印并且不作为不可破坏的空间
替换空格,这样下划线的颜色与背景相匹配,但同样,整个事物直接打印,我也意识到那个跨度无论如何会打破这条线content
元素的宽度,它只是将覆盖的线向右移动,尽管我打开Firefox中似乎有帮助的HTML 所以现在,我的解决方案是使用下划线,但这看起来并不专业。如果你能帮我解决问题,我会很感激。
这是更新后的设置:
HTML :
<span style="color:#fff">_</span>
CSS :
.rotate .content:after
包括大部分CSS,因为谁知道,一些似乎无关紧要的小部分可能会有所作为。
答案 0 :(得分:2)
在这个问题上有很多要涵盖的内容。将来你可能想要多关注一点。让我们开始吧。
首先,您对dompdf如何处理表的印象是正确的。在应用变换之前渲染单元格。实际上,我现在非常确定转换对文档的流程没有影响,只是转换内容的外观。
其次,dompdf目前不支持多页面方向。如果您想使用dompdf,则必须单独创建每个PDF并使用类似pdftk或fpdf / fpdi的内容来组合结果。
第三,position: fixed
不作为页面标题处理,而是作为CSS规范概述,即跨页面持久化。 position: absolute
也按照规范处理(大部分)。根据a)遇到它的页面或b)没有静态定位的第一个父元素,将绝对定位的内容放置在指定的坐标处。
如果您将父元素设置为position: relative
,然后绝对定位其中一个子元素,则子元素将相对于父元素定位。这就是为什么最后引用的问题建议使用样式。它应该在dompdf中工作,除了dompdf的不稳定的表处理导致错误的列宽。
那么如何解决这个问题呢?如果将内容从HTML中删除,则dompdf将使其呈现您指定的宽度。您可以使用CSS添加内容。以下似乎运作良好:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<style type='text/css'>
td {
width: 20px;
}
.rotate .container {
position: relative;
overflow: visible;
}
.rotate .content:after {
width: 150px; height: 150px;
overflow: visible;
content: "Overall Satisfaction";
transform: rotate(-90deg);
transform-origin: center center;
position: absolute; left: -150px; top: -200px;
}
</style>
</head>
<body>
<table border="1">
<thead>
<tr style="line-height: 200px;">
<th><div>Facility</div></th>
<th><div>Date</div></th>
<th><div>Score</div></th>
<th class="rotate"><div class="container"><div class="content"></div></div></th>
</tr>
</thead>
<tbody>
<tr>
<td>Los Angeles</td>
<td>11/12/2010</td>
<td>3.5</td>
<td>2.5</td>
</tr>
<tr>
<td>San Diego</td>
<td>11/17/2010</td>
<td>10.0</td>
<td>10.0</td>
</tr>
</tbody>
</table>
</body>
</html>
确保您使用的是dompdf 0.6.1。
答案 1 :(得分:1)
我遇到了同样的问题并尝试了完美的BrianS的答案 - 第一页。
但是,当表格跨越多个页面(重复标题)时,所有后续页面上的旋转文本都被错误定位。
更多地考虑这个问题,我发现了一个非常简单的解决方案,如果我喜欢,你想要在所有页面上完全相同的旋转文本(如果没有,那么这将不起作用):只是不要画画PDF创建过程中的所有文本,但稍后会像页面编号一样添加它们。
也就是说,只需创建具有所需高度和宽度的单元格,但在实际的HTML布局中将它们留空。
然后像这样添加文本:
// assuming you loaded the HTML,
// create the PDF and grab the canvas
$dompdf->render();
$canvas = $dompdf->get_canvas();
// add rotated text!
$font = Font_Metrics::get_font("helvetica");
$canvas->page_text(250, 50, "Rotated", $font, 9, array(0,0,0), 0, 0, 270);
$canvas->page_text(300, 50, "Text", $font, 9, array(0,0,0), 0, 0, 270);
这里的最后一个参数是旋转角度。注意:那里似乎有不同的dompdf版本,其中一些版本在颜色和旋转之间有两个间距参数(如此处所示),其中一些在颜色和旋转之间有一个间距参数。
答案 2 :(得分:0)
每页不同位置插入信息可以通过内联PHP实现:
$header = array();
foreach($participants_t as $p_id => $p) {
$header[] = $p['Title'];
}
...
$dompdf = new DOMPDF();
$html = htmlspecialchars_decode(htmlentities($html, ENT_NOQUOTES, 'UTF-8'), ENT_NOQUOTES);
$dompdf->load_html($html);
$dompdf->set_paper("A4", "landscape");
$dompdf->render();
$pdf = $dompdf->get_canvas();
$GLOBALS["header"] = $header;
if (isset($pdf)) {
$pdf->page_script(
'$plus_top = 70; '
. 'if ($PAGE_NUM > 1) { '
. '$plus_top = 0; '
. '} '
. '$font = Font_Metrics::get_font("DeJavu Sans"); '
. '$header = array(); '
. '$header = $GLOBALS["header"]; '
. 'foreach($header as $key => $item) { '
. '$pdf->text(122 + 22.01 * $key, 178 + $plus_top, $item, $font, 9, array(0,0,0), 0, 0, -90); '
. '} '
. '');
}
return $dompdf;
所以在第一页($ PAGE_NUM = 1)的最高位置是70px更大。 这种方法有一个问题 - 不为内联PHP插入的文本创建字体子集。
答案 3 :(得分:0)
首先,设置A_LONG_HEADER height:125px
的高度,并在div margin-left: -50px
margin-right: -50px
内部设置左右边距。以下似乎很好用:
HTML
<table id="codexpl">
<tr >
<th >#</th>
<th><span >98</span></th>
<th id="rotate"><div id="vertical">A_LONG_HEADER</div></th>
</tr>
<tr>
<td>1</td>
<td>This</td>
<td>c</td>
</tr>
<tr>
<td>2</td>
<td>6</td>
<td>two</td>
</tr>
<tr>
<td>3</td>
<td>is</td>
<td>not</td>
</tr>
<tr>
<td>4</td>
<td>the</td>
<td>Column</td>
</tr>
<tr>
<td>5</td>
<td>first</td>
<td>One</td>
</tr>
</table>
<p>TEST</p>
CSS
#rotate
{
height:125px;
}
#vertical
{
-webkit-transform:rotate(-90deg);
-moz-transform:rotate(-90deg);
-o-transform: rotate(-90deg);
margin-left: -50px;
margin-right: -50px;
}