tcpdf 的 imageSVG() 方法无法正确呈现 svg 文件
The imageSVG() method of tcpdf is not rendering correctly the svg file
我有以下 svg 文件:
<svg></svg>
呈现:
但是,通过使用 tcpdf ($pdf->imageSVG()),我得到一个呈现的 pdf 文件:
SVG 标准未在 TCPDF 中完全实现,因此并非所有 SVG 都能在 TCPDF 中正确呈现。对于这些情况,您要么需要使用 setRasterizeVectorImages
(需要 ImageMagick)为您即时栅格化 SVG,要么将 SVG 调整为可以工作的形式。
对于这个特定文件,我怀疑路径的复杂性是问题所在。虽然,我不完全确定。我为您制作了一个适用于最新版本 TCPDF 的新 SVG 文件。 I saved it in a JSFiddle here. 基本上,我采用了路径并使用 InkScape 将其分解为单个元素。
为此,我进入了变换组,选择了路径,最后从 路径 菜单中选择了“分开”。
很遗憾该项目不再受到支持,尽管它是我见过的最好的作品之一。对于那些仍在使用它并遇到这个问题的人来说,问题是根据 SVG specs, the "Z" command:
..in a subpath causes an automatic straight line to be drawn from the current
point to the initial point of the current subpath.
这应该"reset"下一个命令的相对路径到子路径的开始。 TCPDF 没有实现这部分;它只是关闭路径,但不会将笔移动到子路径的开头,这是下一个命令的起点。
所以为了解决这个问题,我简单地在受保护的 SVGPath 函数的开头创建了两个变量,并在 "M" (moveto) 开关中设置它们的值存储每个路径或子路径的开始。
然后在 "Z" 开关中,我只是根据规格说明画了一条线回到那个存储点。我已经在不同的 SVG 中测试过它并且工作得很好。这是代码..
对于"M":
case 'M': { // moveto
foreach ($params as $ck => $cp) {
if (($ck % 2) == 0) {
$x = $cp + $xoffset;
} else {
$y = $cp + $yoffset;
if ($firstcmd OR (abs($x0 - $x) >= $minlen) OR (abs($y0 - $y) >= $minlen)) {
if ($ck == 1) {
$this->_outPoint($x, $y);
$firstcmd = false;
} else {
$this->_outLine($x, $y);
}
$x0 = $x;
$y0 = $y;
}
$xmin = min($xmin, $x);
$ymin = min($ymin, $y);
$xmax = max($xmax, $x);
$ymax = max($ymax, $y);
if ($relcoord) {
$xoffset = $x;
$yoffset = $y;
}
$start_x = $x;
$start_y = $y;
}
}
break;
对于"Z":
case 'Z': {
$x = $start_x;
$y = $start_y;
$this->_outLine($x, $y);
$this->_out('h');
break;
变量是:$start_x 和 $start_x 你可以用如果路径不以 moveto 开头,函数开头的 0 值可以避免错误。
我有以下 svg 文件:
<svg></svg>
呈现:
但是,通过使用 tcpdf ($pdf->imageSVG()),我得到一个呈现的 pdf 文件:
SVG 标准未在 TCPDF 中完全实现,因此并非所有 SVG 都能在 TCPDF 中正确呈现。对于这些情况,您要么需要使用 setRasterizeVectorImages
(需要 ImageMagick)为您即时栅格化 SVG,要么将 SVG 调整为可以工作的形式。
对于这个特定文件,我怀疑路径的复杂性是问题所在。虽然,我不完全确定。我为您制作了一个适用于最新版本 TCPDF 的新 SVG 文件。 I saved it in a JSFiddle here. 基本上,我采用了路径并使用 InkScape 将其分解为单个元素。
为此,我进入了变换组,选择了路径,最后从 路径 菜单中选择了“分开”。
很遗憾该项目不再受到支持,尽管它是我见过的最好的作品之一。对于那些仍在使用它并遇到这个问题的人来说,问题是根据 SVG specs, the "Z" command:
..in a subpath causes an automatic straight line to be drawn from the current point to the initial point of the current subpath.
这应该"reset"下一个命令的相对路径到子路径的开始。 TCPDF 没有实现这部分;它只是关闭路径,但不会将笔移动到子路径的开头,这是下一个命令的起点。
所以为了解决这个问题,我简单地在受保护的 SVGPath 函数的开头创建了两个变量,并在 "M" (moveto) 开关中设置它们的值存储每个路径或子路径的开始。
然后在 "Z" 开关中,我只是根据规格说明画了一条线回到那个存储点。我已经在不同的 SVG 中测试过它并且工作得很好。这是代码..
对于"M":
case 'M': { // moveto
foreach ($params as $ck => $cp) {
if (($ck % 2) == 0) {
$x = $cp + $xoffset;
} else {
$y = $cp + $yoffset;
if ($firstcmd OR (abs($x0 - $x) >= $minlen) OR (abs($y0 - $y) >= $minlen)) {
if ($ck == 1) {
$this->_outPoint($x, $y);
$firstcmd = false;
} else {
$this->_outLine($x, $y);
}
$x0 = $x;
$y0 = $y;
}
$xmin = min($xmin, $x);
$ymin = min($ymin, $y);
$xmax = max($xmax, $x);
$ymax = max($ymax, $y);
if ($relcoord) {
$xoffset = $x;
$yoffset = $y;
}
$start_x = $x;
$start_y = $y;
}
}
break;
对于"Z":
case 'Z': {
$x = $start_x;
$y = $start_y;
$this->_outLine($x, $y);
$this->_out('h');
break;
变量是:$start_x 和 $start_x 你可以用如果路径不以 moveto 开头,函数开头的 0 值可以避免错误。