【问题标题】:Calculating SVG bounding box using PHP with respect to curves使用 PHP 计算关于曲线的 SVG 边界框
【发布时间】:2013-04-26 23:51:17
【问题描述】:

我最近发现了这个位于here 的神奇课程,并尝试使用它。

但是,它只适用于移动、水平线和垂直线等一些基本功能。

--

我已经尝试通过添加额外的检查(并更改正则表达式)来扩展这个现有的类。

public static function fromPath($pathString) {
    preg_match_all('/([mlvhzc][^mlvhzc]*)/i', $pathString, $commands);
    $pt = array(0, 0);
    $bounds = new self();
    foreach ($commands[0] as $command) {
        preg_match_all('/((\+|-)?\d+(\.\d+)?(e(\+|-)?\d+)?)/i', $command, $matches);
        $i = 0;
        while ($i < count($matches[1])) {
            switch ($command[0]) {
                case 'm' :
                case 'l' :
                    $pt[0] += $matches[1][$i++];
                    $pt[1] += $matches[1][$i++];
                    break;
                case 'M' :
                case 'L' :
                    $pt[0] = $matches[1][$i++];
                    $pt[1] = $matches[1][$i++];
                    $last=$pt;
                    break;
                case 'v' :
                    $pt[1] += $matches[1][$i++];
                    break;
                case 'V' :
                    $pt[1] = $matches[1][$i++];
                    $last[1]=$pt[1];
                    break;
                case 'h' :
                    $pt[0] += $matches[1][$i++];
                    break;
                case 'H' :
                    $pt[0] = $matches[1][$i++];
                    $last[0]=$pt[0];
                    break;
                case 'z' :
                case 'Z' :
                    break;
                case 'c':
                    $pt[0] = $last[0]+$matches[1][4];
                    $pt[1] = $last[1]+$matches[1][5];
                    $last=$pt;
                    $i=count($matches[1]);
                    break;
                default :
                    throw new RuntimeException("Unhandled path command: " . $command[0]);
            }
            $bounds->extend($pt[0], $pt[1]);
        }

    }
    return $bounds;
}

我查看了 SVG 手册,发现“c”只有 6 个参数,知道最后 2 个是曲线最终的位置,因此我尝试基于此扩展点...

目前,我的测试基于此:

<svg xmlns="http://www.w3.org/2000/svg" width="109" height="109" viewBox="0 0 109 109">
<g style="fill:none;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;">
    <path d="M32.25,41c1.25,0.62,3.12,0.67,5.5,0.5c7.12-0.5,19.12-2.5,24-3c0.99-0.1,2.62-0.25,3.75,0" />            
</g>

当在浏览器中运行时,Chrome 报告它的宽高比(因为我知道 svg 并不完全有大小),大约是 5 到 6,但是,当我用我的脚本找到该比例时,它完全关闭了.

我想知道是否有另一个支持所有函数(C、c、Q、q 等)的 svg 类。

我知道有一种方法可以通过将它转换为图像来获取盒子,但我觉得效率低下,javascript中也有getBBox,但我想在服务器上执行计算。

感谢阅读!

【问题讨论】:

  • 这不是将图像渲染为 png/jpg 吗?如果可能的话,我想用数学来做这些计算。
  • 它可以处理任何类型的图像,并且可以轻松使用它,准确地获取边界框,假设 $image 是一个 imagick 对象,函数 $image->readImage('./some/path/image .svg');允许您读取和加载 svg,您可以使用其他可用功能对其进行处理,您可以将其(加载的图像)转换为 png/jpg 或将其保留为 svg,这取决于您。阅读 php imagick,它会让你的生活更轻松。
  • 我正在从数据库中加载 svg,没有保存文件,如何将图像导入 imagick 类,
  • 你可以试试 $image->readImageBlob(String imagestring);

标签: php svg bounding


【解决方案1】:

这是一个使用imagick的示例,实际上是两个示例,因为它们不能同时运行,请取消注释一个:

$svg = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" width="109" height="109" viewBox="0 0 109 109">
<g style="fill:none;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;">
    <path d="M32.25,41c1.25,0.62,3.12,0.67,5.5,0.5c7.12-0.5,19.12-2.5,24-3c0.99-0.1,2.62-0.25,3.75,0" />            
</g>
</svg>';

$im = new Imagick();
$im->readImageBlob($svg);
$im->trimImage (0);//This trims the unecessary blank space.

//This block gets the dimensions (comment this block before uncommenting the second example bellow)
$dimension = $im->getImageGeometry();
print_r('<pre>');
print_r($dimension);
die();


/*//Uncomment this block to view thw jpeg version of the svg
$im->setImageFormat("jpeg");
header("Content-Type: image/jpeg");
$thumbnail = $im->getImageBlob();
echo $thumbnail;
$im->clear();
$im->destroy();
//*/

【讨论】:

  • PHP Imagick 是一个非常强大的工具,您应该阅读它。我敢肯定,它会为您省去很多麻烦。
  • 嗨! Imagick 响应:宽度和高度为 109,如果我从 svg 中删除这些属性,则会产生错误。
  • 它响应 array("width"=>109,"height"=>109)。
  • 您不是在寻找 svg 的宽度和高度吗?
  • 边界框,被认为是svg可以在没有剪辑的情况下绘制的最小空间。
【解决方案2】:

Hermann's answer 帮了我很多,但实际上并没有修剪 SVG。以下是我根据他的回答得出的第一个解决方案:

function getTrimmedSvg( $filePath )
{
    $image = new Imagick();
    $image->readImage( $filePath );
    $image->trimImage( 0 );

    $imagePage = $image->getImagePage();
    $dimensions = $image->getImageGeometry();

    $minXOut = $imagePage['x'];
    $minYOut = $imagePage['y'];
    $widthOut = $dimensions["width"];
    $heightOut = $dimensions["height"];

    $xml = simplexml_load_file( $filePath );

    $xml["viewBox"] = "$minXOut $minYOut $widthOut $heightOut";

    return $xml->asXML();
}

虽然这在大多数情况下都有效,但并非始终有效。在尝试修复边缘情况的许多徒劳无功之后,我转而使用名为 svg-bounding-box (GitHub) 的 nodejs 命令行实用程序。这解决了我所有的边缘情况。在您的服务器和/或开发环境上全局安装 svg-bounding-box 后,您可以通过以下方式在代码中使用它:

function getTrimmedSvg( $filePath )
{
    $xml = simplexml_load_file( $filePath );

    $xml["viewBox"] = shell_exec( "cat $filePath | svg-bounding-box" );

    return $xml->asXML();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多