【问题标题】:Width of Rotated Table Headers in DOMPDFDOMPDF 中旋转表格标题的宽度
【发布时间】:2015-03-21 06:25:24
【问题描述】:

我有一张大桌子,里面有很多列,我需要使用 DOMPDF 将它们放入 PDF 页面。就像here一样,我的标题比相应的内容要宽得多,所以我正在尝试旋转它们。在 Firefox 中打开的 HTML 似乎没问题,但生成的 PDF 不是。

设置

HTML

<td class="cell rotated_vertical_td" style="width:3%;">
    <div class="rotated_vertical">Rotated_</div>
</td>

上面的宽度属性是在 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;
}

我不得不对每个 &lt;td&gt; 应用 .cell 类,因为 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 元素视为页眉,可能会为绝对定位的元素保留一些内容。

请帮忙

2015-01-26 更新

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

我想为那些在这里寻找解决方案的人指出几件事(包括我猜的未来我)

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

    transform-origin: left bottom 0;
    

    ...只是它的位置不那么随机,因为否则会改变 either top/left or width/height 属性不断移动块在两个维度。事实上有大约 7 个变量需要控制(:after 元素的top,left,width/height,以及 line-heightwidth/height包装单元格)使得不可能通过所有可能的组合来获得理想的位置。

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

我找不到阻止这种情况的方法。看到不包含任何易碎字符的文本仍然放在一行中,

  • 尝试使用宽度/高度/行高控件
  • 尝试用 css content 属性内的 &amp;nbsp; 替换空格,但它会直接打印出来,并且不能用作不可破坏的空格
  • 尝试将 ASCII 字符用作 advised here,但它会输出一些奇怪的字符
  • 用下划线替换了空格 - 它可以工作但看起来很难看
  • 所以我尝试用&lt;span style="color:#fff"&gt;_&lt;/span&gt; 替换空格,这样下划线的颜色与背景匹配,但同样,整个内容都会直接打印出来,而且我也意识到该跨度会打破界限无论如何
  • 感觉组合起来的那条线没有足够的宽度,但是如果我更改.rotate .content:after 元素的宽度,它只会将覆盖的线向右移动,尽管当我在 Firefox 中打开 HTML这似乎有帮助

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

这是更新后的设置:

HTML

<tr class="table_summary_thead">
    <td class="rotated_vertical_td" style="width:3%;">
        <a hred="appendix_item_44">
            <div class="rotated_vertical_outer">
                <div class="rotated_vertical_inner rtb1f73b0b57649457abd0ca2e0e8c94e0f7d79c25">
                </div>
            </div>
        </a>
        <style type="text/css">
            .rtb1f73b0b57649457abd0ca2e0e8c94e0f7d79c25:after {
                content:"COMPREHENSIVE";
            }
        </style>
    </td>
</tr>

CSS

.table_summary {
    width:100% !important;
}
.table_summary td {
    text-align:center;
}
.table_summary tbody td {
    font-size: 10pt;
    padding: 4px;
}
.rotated_vertical_td {
    width: 20px !important;
    height: 680px !important;
    font-size: 8pt;
    margin:0;
    padding:0;
    text-align:left;
}
.table_summary_thead {
    line-height: 220px;
    text-align:left;
}
.rotated_vertical_outer {
    position: relative;
    overflow: visible;
    text-align:left;
}
.rotated_vertical_inner:after {
    height: 150px;
    overflow: visible;
    position: absolute;
    text-align: left;
    transform: rotate(270deg);
    transform-origin: left bottom 0;
    width: 20px;
    top: 100px;
    left: 110px;
}

这里包括大部分 CSS,因为谁知道呢,一些看起来无关紧要的小部分可能会有所作为。

【问题讨论】:

  • 我感觉定位元素会很痛苦。我希望我能够提出更好的选择。
  • 另请注意,dompdf 目前不能很好地处理不间断空格。它们几乎被视为常规空间。
  • 为了确保您的行不会中断,您应该能够使用white-space: nowrap; 设置:after 块的样式。 (这可能会导致您不得不重新定位。)

标签: css rotation dompdf rotatetransform


【解决方案1】:

这个问题有很多内容。将来,您可能希望更加专注。让我们开始吧。


首先,您对 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。

【讨论】:

  • @BrianS 感谢您的帮助。我已经尝试过了,并发布了对该问题的更新。请看上面
【解决方案2】:

我遇到了同样的问题,并尝试了 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 版本,其中一些在颜色和旋转之间有两个间距参数(如图所示),其中一些在颜色和旋转之间有一个间距参数。

【讨论】:

    【解决方案3】:

    首先,设置A_LONG_HEADER的高度height:125px,并设置div内部的左右边距margin-left: -50pxmargin-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;
    }
    

    【讨论】:

      【解决方案4】:

      在每页不同的地方插入信息可以通过内联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) 顶部位置大了 70 像素。 这种方法有一个问题 - 没有为内联 PHP 插入的文本创建字体子集。

      【讨论】:

        猜你喜欢
        • 2020-01-02
        • 1970-01-01
        • 2016-11-22
        • 2012-09-23
        • 1970-01-01
        • 2013-12-30
        • 1970-01-01
        • 2011-10-09
        • 2020-04-30
        相关资源
        最近更新 更多