3

最近、この素晴らしいクラスがここにあるのを見つけて、使ってみました。

ただし、移動、水平線、垂直線などの一部の基本機能でしか機能しません。

--

追加のチェックを追加して(および正規表現を変更して)、この既存のクラスを拡張しようとしました。

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 がありますが、サーバー上で計算を実行したいと考えています。

読んでくれてありがとう!

4

2 に答える 2

3

これは imagick を使用した例です。同時に実行することはできないため、実際には 2 つの例が 1 つになっています。一度に 1 つずつコメントを外してください。

$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();
//*/
于 2013-05-02T20:05:14.700 に答える
1

ヘルマンの答えは私を大いに助けてくれましたが、実際には 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();
}
于 2016-12-14T21:37:25.623 に答える