如何通过PHP旋转SVG [英] How to rotate SVG by PHP

查看:90
本文介绍了如何通过PHP旋转SVG的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想通过PHP旋转SVG.

I want to rotate SVG by PHP.

我有SVG文件,想通过PHP旋转它们. 我在网上找到的方法是添加类似的内容

I have SVG files and want to rotate them by PHP. The method I found online is to add something like

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

在< svg>内部.

inside <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>

但是现在我不知道如何实现-

but now I don't know how to achieve this -

  1. < svg> 内添加 < g> 节点.

  1. to add a <g> inside <svg> and wrap all old inner nodes.

如果 < g> 已经包装了所有内部节点,则跳过 添加新的< g>标签,但只需将其旋转到新的高度即可.

if <g> is already wrapping all inner nodes, then skip adding new <g> tag but just rotate it to a new degree.

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

the following is a possible svg code before rotating.

    <?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>

推荐答案

我搜索了很长时间,最后将它们放在一起.希望对您有所帮助.

I searched for quite awhile and finally put this together. Hope it helps.

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

You can use the SimpleXML Library to access the nodes as needed.

我的解决方案有效,但可能可以简化.

My solution works, but could probably simplified.

首先,我添加了此类(在此处的注释中找到):

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); 
            } 
         } 
     } 
} 

只需在任何代码之前添加它.

Just include that before any of the code.

//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,这对我来说都非常有效.可能有更简单的方法,但这肯定是有效的.

This worked quite well for me for both SVG's wrapped in a tag and those that weren't. There might be simpler ways to do it, but this is certainly effective.

还有一件事! 这可能不正确,但是当我旋转SVG时,它们通常会被剪断.因此,我不得不更改主要属性.随之而来的是交换高度和宽度,以及转换SVG使其重新居中.在这里,您去了:

One more thing! This may not be correct but when I rotated my SVG's, they were usually clipped. Thus I had to alter the main attributes. What this entailed was swapping the height and width, as well as translating the SVG to re-center it. Here you go:

//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");

您可能会注意到,该代码也将逆转旋转过程.

You may notice towards the bottom, this code will also reverse the rotation process as well.

希望有帮助!

这篇关于如何通过PHP旋转SVG的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆