Как повернуть SVG с помощью PHP

Я хочу повернуть SVG с помощью PHP.

У меня есть файлы 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'); с //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 для повторного центрирования. Ну вот:

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

Вы можете заметить снизу, этот код также изменит процесс вращения.

Надеюсь, это поможет!