mPDF 图像以裁剪且无失真的方式覆盖页面

Posted

技术标签:

【中文标题】mPDF 图像以裁剪且无失真的方式覆盖页面【英文标题】:mPDF image to cover page with crop and no distortion 【发布时间】:2018-05-12 15:55:05 【问题描述】:

我已经尝试了所有可以想象的组合来获得看起来如此简单的东西。

我需要在 A4 (210mm (h) X 297mm (w)) 的页面上放置一张图片,并让该图片的高度为 100%,即 297mm,然后按比例拉伸宽度并裁剪溢出(即隐藏在 css 溢出中)。我已经尝试了所有我能想到的与$mpdf->Image() 的组合,或者就像我在 PDF 文件中的其他任何地方所做的那样,使用纯 html 和 CSS。例如

<img src="path(to/file.jpg" />

<div style="background: url("path(to/file.jpg") center center no-repeat;"></div>

再次,我能想到的所有可能的 CSS 配置。

是否可以拉伸和图像以适应整个页面高度,同时保持纵横比并裁剪两侧的图像?

我在MPDF full page background 上看到过background-image-resize,但还是没有。

如何使图像达到页面高度的 100%(我不在乎是否必须定义高度(即 297 毫米)或是否是百分比)使图像比例与该高度成比例并裁剪任何侧面的图像过多。

我确定我在这里错过了一些明显的东西。我看不出我做错了什么(我想我现在陷入了一个循环)。

如果我在浏览器中执行回显和查看,则显示良好(如预期)的示例

$html = '<div style="
    background: url('.$imageSource.') center center no-repeat;
    position: absolute;
    overflow: hidden;
    height: 297mm;
    width: 100%;
    background-size: cover;
    top: 0;
    left: 0;
"></div>';

但是,对$pdf-&gt;WriteHTML( $html, 2 )$pdf-&gt;Output() 执行相同操作,图像的高度为 297 毫米,但宽度变形(即它不会与高度成比例地拉伸)。

这是生成的 PDF(带有占位符图像)

这就是我想要实现的目标

因此生成的 PDF 会被“压缩”。而不是将宽度与高度 (297mm) 成比例地扩展。

PS. 抱歉,缺少实际测试过的代码。但是我尝试过的不同组合太多了,我无法重现所有这些组合。

PPS。使用最新版本的 mPDF。三天前从 GitHub 上抓取的。

【问题讨论】:

如果您可以添加您的代码现在生成的屏幕截图可能会有所帮助(它与您想要的有什么不同?)。此外,由于您使用的是 php,因此您可以读取图像的尺寸,然后添加明确的宽度和高度(特别是因为您要渲染到具有固定尺寸的页面,例如 A4 纵向)。 还要记住,PDF 渲染中的 CSS 解析器将比浏览器更不完整,所以不要期望太多。我认为最好的可能是PrinceXML,但商业版并不便宜。 @halfer 感谢您的修剪(一直在转圈)。我添加了图像来说明结果与预期结果。我已经尝试过 PHP 和 getimagesize() 的宽度和高度。尽管如此,结果始终是扭曲的图像。我不明白为什么图像不能有高度 > 可见宽度而只是裁剪溢出。 图片的纵横比和页面一样吗?如果是这样,我不明白为什么使用getimagesize 的正确输出不起作用。 图片为 1024x680px(宽x高。但这可能会有所不同),所以没有。这就是为什么我需要图像是页面的全高,按比例拉伸宽度并保持图像比例。所以无论有什么溢出都会被裁剪(隐藏)。但它现在所做的只是扭曲图像。 【参考方案1】:

由于我在逻辑、CSS 和数学方面遇到了很多问题,我想我会在这里与其他为此苦苦挣扎的人分享我的最终工作解决方案。 从函数开始

function image( $containerWidth, $containerHeight, $imageSource, $top, $left, $border )
// Get image width
$imageWidth             = getimagesize( $imageSource )[0];
// Get image height
$imageHeight            = getimagesize( $imageSource )[1];
// Get image aspect ratio
$imageRatio             = $imageWidth / $imageHeight;
// Get container aspect ratio
$containerRatio         = $containerWidth / $containerHeight;
// Decide if image should increase in height or width
if( $imageRatio > $containerRatio )
    $width                  = ( ( $imageRatio / $containerRatio ) * 100 );
else
    $width                  = ( ( $containerRatio / $imageRatio ) * 100 );

if( $border )
    // $border array: 0 = thicknes in points, 1 = type (solid, dotted etc), 2 = color
    $border = 'border: '.$border[0].'pt '.$border[1].' '.$border[2].';';

return '<div style="position: absolute; top: '.$top.'mm; left: '.$left.'mm; width: '.$containerWidth.'mm; height: '.$containerHeight.'mm; overflow:hidden; margin:0;'.$border.'"><img src="'.$imageSource.'" style="width: '.$width.'%; margin: 0 -'.( ( $width - 100 ) / 2 ).'%;" /></div>';

然后是居中的整页图片

$image1                     = image( 210, 297, $imageSource[0], 0, 0, null );

或者两张图片重叠在一起,一张有白色边框

$image2                     = image( 105, 148, $imageSource[1], 15, 15, null );
$image3                     = image( 105, 148, $imageSource[2], 133, 90, [ 10, 'solid', 'white' ] );

输出

// mPDF options array
$pdfOptions = array(
    'mode'              => 'utf-8',
    'format'                => 'A4',
    'img_dpi'               => 300,
    'dpi'                   => 300,
);
// Declare $pdf and set options
$pdf                    = new \Mpdf\Mpdf( $pdfOptions );
// Stylesheets
$style                  = file_get_contents( __DIR__ . '/path/to/stylesheet.css');
$pdf->WriteHTML( $style, 1 );
$pdf->WriteHTML( $image1, 2 );
$pdf->AddPage();
$pdf->WriteHTML( $image2, 2 );
$pdf->WriteHTML( $image3, 2 );
$pdf->Output();

【讨论】:

以上是关于mPDF 图像以裁剪且无失真的方式覆盖页面的主要内容,如果未能解决你的问题,请参考以下文章

从 iPhone 的照片库中调整方形裁剪图像的正确方法而不会失真

mPDF:为整页使用背景图像

在 OpenCV (Python) 中使用校正失真裁剪图像

使用 CSS 裁剪和拉伸图像以填充页面 [重复]

将背景图像复制到使用 mpdf 生成的 pdf 中的其他页面

如何裁剪html页面,而不是图像