如何用PHP旋转SVG


How to rotate SVG by PHP

我想用PHP旋转SVG。

我有SVG文件,想用PHP旋转它们。我在网上找到的方法是添加类似的东西

    <g transform="translate(90) rotate(45 50 50)">

内部<svg>。

例如,我想从转换

<svg> <i-am-here+i-was-here>...</i-am-here+i-was-here> </svg>

<svg> <g transform="i-have-transform-but-no-rotate"> <i-am-here+i-was-here>...</i-am-here+i-was-here> </g> </svg>

收件人:

<svg> <g transform="svgrotate+old-transform"> <i-am-here+i-was-here>...</i-am-here+i-was-here> </g> </svg>

但现在我不知道如何做到这一点-

  1. 添加<g>内部<svg>并包裹所有旧的内层节点。

  2. 如果<g>已经包装了所有内部节点,然后跳过添加新<g>标记,但只是将其旋转到一个新的程度。

以下是旋转之前可能的svg代码。

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
    <svg version="1.1" id="hello" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
         width="800px" height="700px" viewBox="0 0 800 700" enable-background="new 0 0 800 700" xml:space="preserve">        
    <g>
      <path transform="rotate(-14.1173 121.2 96.1965)" id="svg_2" d="m128,25c9,14 9,204 -35,124c-44,-80 177,-52 120,-36c-57,16 -120,-77 -185,-79c-65,-2 288,166 169,128c-119,-38 -78,-151 -69,-137z" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="0" stroke="#3f007f" fill="#f4f438"/>
      <path transform="rotate(152.959 126.708 104.715)" stroke="#3f007f" id="svg_3" d="m219.4411,94.86682c-50.99725,81.80002 -148.00278,74.4472 -190.13092,50.55057c-42.12811,-23.89664 5.54315,-43.19778 18.8468,-19.30115c13.30362,23.89664 81.48468,16.54382 108.64624,0.91913c27.16156,-15.62473 50.44287,-45.95508 54.87738,-56.06519c4.43463,-10.11011 58.75769,-57.90341 7.7605,23.89664z" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="0" fill="#7fff00"/>
    </g>
    <path transform="rotate(9.48719 272.234 246.106)" id="svg_6" d="m214,78c0,-1 -108,23 -108,23c0,0 -85,108 23,85c108,-23 122,32 167,14c45,-18 -64,289 106,197c170,-92 -31,-310 -32,-310" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="0" stroke="#3f007f" fill="#ffaad4"/>
    <path d="m342,184c-7,-2 -12.98453,-3.08075 -18,-4c-5.98309,-1.0966 -11.53976,-2.46873 -19,-4c-5.87747,-1.20639 -13,-1 -18,-1c-7,0 -14.05798,-0.83221 -20,0c-7.20975,1.00977 -14.33942,4.12776 -23,8c-7.36008,3.29077 -14.23541,7.73578 -21,14c-5.1882,4.80443 -11.03857,10.11638 -16,17c-5.22981,7.25597 -7.48169,14.87997 -9,22c-1.47472,6.91557 -1.49489,14.02045 -1,20c0.50171,6.06204 3,11 5,16c2,5 3.72398,9.22272 7,13c3.70638,4.2735 5,5 6,5l1,0l3,-1" id="svg_1" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="0" stroke="#000000" fill="none"/>   
    <g>  
      <path stroke="#000000" transform="rotate(-7.76776 324.596 222.303)" id="svg_4" d="m422.29062,129.05128c-126.20798,34.85936 91.52487,198.50475 -153.18372,103.60979c-244.70862,-94.89496 238.92807,178.17014 107.90298,114.26129c-131.02509,-63.90884 65.51254,-336.00563 -15.4147,-153.96223c-80.92725,182.04341 -141.62271,231.42751 -145.47639,168.48695c-3.85367,-62.94052 213.8792,-386.35803 113.68355,-284.68486c-100.19566,101.67317 67.43936,149.12065 111.75668,227.55424c44.31729,78.43359 -92.48828,66.81381 -114.64694,62.94052c-22.15866,-3.87326 184.97659,-174.29686 23.12207,-215.93445c-161.85452,-41.63758 -53.95151,-3.87326 -52.02466,114.26129c1.92682,118.13455 1.92682,118.13455 1.92682,118.13455" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="0" fill="#ff0000"/>
      <path transform="rotate(20.3513 424.5 303.53)" stroke="#000000" id="svg_5" d="m368,255.68533l113,37.43481c0,0 13.37784,104.74188 -53.79596,69.57584c-67.17383,-35.16605 32.16373,-157.30188 -21.06299,-117.59828c-53.22668,39.7036 -53.22668,39.7036 -53.22668,39.7036" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="0" fill="#007fff"/>  
    </g>
    <path transform="rotate(44.7788 399.595 115.757)" id="svg_8" d="m354,84c8,54 10,126 56,59c46,-67 42,-57 16,-76c-26,-19 -72,17 -72,17z" stroke-linecap="null" stroke-linejoin="null" stroke-dasharray="null" stroke-width="0" stroke="#3f007f" fill="#7f7f00"/>
    </svg>

我搜索了很长一段时间,终于把这些放在了一起。希望能有所帮助。

您可以根据需要使用SimpleXML库来访问节点。

我的解决方案有效,但可能会简化。

首先,我添加了这个类(可以在这里的评论中找到):

class ExSimpleXMLElement extends SimpleXMLElement 
{ 

    public function _construct($xml){
        parent::_construct($xml);
    }
    /** 
     * Add SimpleXMLElement code into a SimpleXMLElement 
     * @param SimpleXMLElement $append 
     */ 
    public function appendXML($append) 
    { 
        if ($append) { 
            if (strlen(trim((string) $append))==0) { 
                $xml = $this->addChild($append->getName()); 
                foreach($append->children() as $child) { 
                    $xml->appendXML($child); 
                } 
            } else { 
                $xml = $this->addChild($append->getName(), (string) $append); 
            }     
            foreach($append->attributes() as $n => $v) { 
                $xml->addAttribute($n, $v); 
            } 
         } 
     } 
} 

只需将其包含在任何代码之前。

//file
$file = 'svg-nog.svg';
//http://www.webdeveloper.com/forum/showthread.php?165648-Editing-XML-using-PHP
$xml = simplexml_load_file($file); //Load the File. 
$sxe = new EXSimpleXMLElement($xml->asXML()); //Load the child class (it will load the main one)
// Get the parent node's childrens
$nodeChildrens = $sxe->children();
//Check if there's more than one child and if there is more than one <g> tag
if(count($nodeChildrens) > 1 and count($sxe->g) > 1){
//Add our Wrapper Node
$g = $sxe->addChild("g");
//You can go ahead and add your desired transform code
$g['transform'] = "rotate(90 600 600)";
//Set an ID so it's unique
$g['id'] = "myWrapper";
$unsets = array();
//Loop through the children
foreach ($nodeChildrens as $value) {
            //Skip our wrapper element
    if($value->attributes()->id == "myWrapper"){
        continue;
    }
            //Append the element to the wrapper
            //Will recursively add elements as needed
    $g->appendXML($value);
    //Save a reference for the different elements we have
    $unsets[] = $value->getName();
}   
//Loop through the old/loose elements and remove them
foreach ($unsets as $name) {
    $segarr = $sxe->{$name};
    $count = count($segarr);
    $j = 0;
    for ($i = 0; $i < $count; $i++) {
        if ($segarr[$j]['id'] != 'myWrapper') {
            unset($segarr[$j]);
            $j = $j - 1;
        }
        $j = $j + 1;
    }
}
} else {
    //Just apply the transform
    $sxe->g['transform'] = "rotate(90 600 600)";
        //Can also be done with:
        //$sxe->g->addAttribute('transform', "rotate(90 600 600)");
}
//Save
$sxe->asXML('test.svg');

这对我来说非常有效,既适用于包装在标签中的SVG,也适用于未包装的SVG。也许有更简单的方法可以做到这一点,但这肯定是有效的。

还有一件事这可能不正确,但当我旋转SVG时,它们通常会被剪切。因此,我不得不改变主要属性。这需要交换高度和宽度,以及转换SVG以重新居中

//Set the vars of the primary attributes we want to edit
$w = "width";
$h= "height";
$viewbox = "viewBox";
$bg = 'enable-background';
//Get SVG Width & Height
$width = (string)$sxe->attributes()->$w;
$height = (string)$sxe->attributes()->$h;
//Get viewBox and background
$sxe->attributes()->$viewbox = "0 0 " . str_replace('px', '', $height) . " " . str_replace('px', '', $width);
$sxe->attributes()->$bg = "new 0 0 " . str_replace('px', '', $height) . " " . str_replace('px', '', $width);
//Get the numerical values for width and height
$rw = floatval(str_replace("px", "", $width));
$rh = floatval(str_replace("px", "", $height));
//Get the center point
$rx = $rw / 2;
$ry = $rh / 2;
//Logic will determine the appropiate translate value for the svg so that it will center in the new viewbox
if($rw < $rh){
    $trans = ($rw - $rh) / 2;
}
if($rw > $rh){
    $trans = -1 * ($rh - $rw) / 2;
}
//Swap width and height
$oldW = (string)$sxe->attributes()->$w;
$sxe->attributes()->$w = $height;
$sxe->attributes()->$h = $oldW;

// Get the parents node childrens
$nodeChildrens = $sxe->children();
//If the transform attribute is set, this svg has already been rotated, as such, we'll just unset it
if(isset($nodeChildrens->g->attributes()->transform)){
    unset($nodeChildrens->g->attributes()->transform);
} else {
    // Otherwise, we're going to add in the transform data for the rotation and re-centering.
    $nodeChildrens->g->addAttribute('transform', "rotate(90 ".$rx." ".$ry.") translate(".$trans." ".$trans.")");
}
//This next line will overwrite the original XML file with new data added 
$sxe->asXML("test.svg");

您可能会注意到,在底部,此代码也将反转旋转过程。

希望能有所帮助!