DOMPDF中旋转表标题的宽度

时间:2015-01-22 12:45:54

标签: css rotation dompdf rotatetransform

我有一个包含大量列的大表,我需要使用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个字符。看起来列宽正在相应调整。

2 characters 4 characters 8 characters

这些是正在呈现的实际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元素视为页眉,可能会为绝对定位元素保留一些内容。

请帮忙

更新2015-01-26

感谢 BrianS 的帮助,我设法使用他建议的CSS方法和从GitHub下载的最新DOMPDF来使文本轮换。在此之前,我正在为每个标题生成带有旋转文本的动态图像。

我想为那些到处寻找解决方案的人指出一些事情(包括未来的我猜)

  1. 定位内容是一场噩梦。似乎没有办法可预测地控制旋转标题的位置和行为,既不在Firefox中,也不在DOMPDF中,并且 令人沮丧。首先,我必须将transform-origin属性更改为:

    transform-origin: left bottom 0;
    

    ...只是因为它的位置不那么随机,因为否则 <{em> top / left {{1} } / width属性保持在两个维度中移动块。事实上有大约7个变量可以控制height元素的topleftwidth / height以及{{1和包裹单元格的:after / line-height使得无法通过所有可能的组合来获得理想的位置。

  2. 如果标题太长并且包含任何易碎字符(例如空格),则会将其拆分为多行,并通过相互叠加将这些行合并为一行。请参阅:

  3. 我无法找到预防这种情况的方法。看到不包含任何易碎字符的文本仍然放在一行上,

    • 尝试使用宽度/高度/线高控件
    • 尝试用css width属性中的height替换空格,但是直接打印并且不作为不可破坏的空间
    • 尝试使用ASCII字符作为advised here,但它会输出一些奇怪的字符
    • 用下划线替换空格 - 它有效,但看起来很难看
    • 所以我尝试用&nbsp;替换空格,这样下划线的颜色与背景相匹配,但同样,整个事物直接打印,我也意识到那个跨度无论如何会打破这条线
    • 感觉就像合并的那条线只是没有足够的宽度,但是如果我改变content元素的宽度,它只是将覆盖的线向右移动,尽管我打开Firefox中似乎有帮助的HTML

    所以现在,我的解决方案是使用下划线,但这看起来并不专业。如果你能帮我解决问题,我会很感激。

    这是更新后的设置:

    HTML

    <span style="color:#fff">_</span>

    CSS

    .rotate .content:after

    包括大部分CSS,因为谁知道,一些似乎无关紧要的小部分可能会有所作为。

4 个答案:

答案 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;
}