PHP SVG编辑 [英] PHP SVG editing

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

问题描述

例如,我正在尝试从svg中读取样式块,我可以获取类型,但不能获取字符串.

For example I am trying to read the style block from an svg, I can get the type but not the string.

$svgTemplate = new SimpleXMLElement($_POST['SvgTemplateImport']);
$svgTemplate->registerXPathNamespace('svg', 'http://www.w3.org/2000/svg');
$svgTemplate->registerXPathNamespace('xlink', 'http://www.w3.org/1999/xlink');

//I tried a bunch of things and this how far I got
$test[] = $svgTemplate->xpath('/svg:svg/svg:style');
$test[] = $result[0][0]['type'];

var_dump($test);

如何检索样式字符串?
如何设置样式字符串?
如何复制组并更改其属性? (例如翻译x和y)?

How to retrieve the style string?
How to set the style string?
How to copy a group and change attributes on it? (like translate x and y)?

我还想更改svg的分辨率和视图框,但是我可以从答案中找出答案.

I also want to change the resolution and viewbox of the svg among other things, but I will be able to figure those out from the answer.

谢谢.

见我的svg:我评论了我想要实现的目标.

See my svg: I commented what I want to achieve.

<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" width="460px" height="200px" viewBox="0 0 460 200" style="enable-background:new 0 0 460 200;" xml:space="preserve">
<style type="text/css">/* new style */</style>
<!-- I did cut the unrelevant parts out-->
<symbol id="MoonFull" viewBox="0 0 100 100">
    <path style="fill:#FFFFFF;" d="M50,99.33C22.8,99.33,0.67,77.2,0.67,50S22.8,0.67,50,0.67S99.33,22.8,99.33,50S77.2,99.33,50,99.33   z"/>
    <path style="fill:#231F20;" d="M50,1.35c26.83,0,48.65,21.82,48.65,48.65S76.83,98.65,50,98.65S1.35,76.83,1.35,50   S23.17,1.35,50,1.35 M50,0C22.39,0,0,22.39,0,50s22.39,50,50,50s50-22.39,50-50S77.61,0,50,0L50,0z"/>
</symbol>
<symbol id="Star" viewBox="0 0 100 100">
    <path id="Star" style="fill:#00FF00;" d="M50,3.58L62.5,39H100L70.83,60.95l10.42,34.93L50,74.81L18.75,95.53l10.42-34.51L0,39  h37.5L50,3.58z"/>
</symbol>
<g id="TemplateForm">
    <g id="twd">
        <rect id="twdCanvas" x="7.3" y="9.32" class="st0" width="263.03" height="72"/>
        <text id="twdWeekdayshorttext" transform="matrix(1 0 0 1 249.5817 41.9174)"><tspan x="0" y="0" class="st2 st3">C</tspan><tspan x="-1.2" y="29.13" class="st2 st3">S</tspan></text>
        <text id="twdDatenumber" transform="matrix(1 0 0 1 41.5544 69.5698)" class="st5 st6">26</text>
        <line id="twdDivider" class="st7" x1="126.49" y1="9.32" x2="126.49" y2="81.32"/>
        <g id="twdText">
            <text id="twdTextLine3" transform="matrix(1 0 0 1 135.0475 28.1718)" class="st2 st8">1234567890abcdef12345</text>
            <text id="twdTextLine2" transform="matrix(1 0 0 1 135.0475 41.5319)" class="st2 st8">1234567890abcdef12345</text>
            <text id="twdTextLine1" transform="matrix(1 0 0 1 135.0475 54.892)" class="st2 st8">1234567890abcdef12345</text>
            <text id="twdTextLine0" transform="matrix(1 0 0 1 135.0475 68.252)" class="st2 st8">1234567890abcdef12345</text>
        </g>
        <line id="twdDateNumAliignerLeft" class="st0" x1="120.02" y1="17.39" x2="120.02" y2="72.07"/>
        <rect id="twdBoxStar" x="15.68" y="19.75" class="st0" width="21" height="21"/>
        <rect id="twdBoxText" x="132.49" y="17.39" class="st0" width="107.92" height="54.68"/>
        <rect id="twdBoxMoon" x="15.68" y="49.15" class="st0" width="21" height="21"/>
    </g>
    <g id="tcl">
        <rect id="tclCanvas" x="7.3" y="153.31" class="st0" width="263.03" height="36"/>
        <line id="tclDivider" class="st7" x1="126.49" y1="153.31" x2="126.49" y2="189.31"/>
        <text id="tclYear" transform="matrix(1 0 0 1 59.1393 183.5269)" class="st2 st9">YYYY</text>
        <text id="tclMonthname" transform="matrix(1 0 0 1 130.9372 182.7798)" class="st2 st10">monthname</text>
    </g>
</g>
<g id="result"><!-- this group will be generated -->
    <!-- this is made from: #twd and added transformation-->
    <g id="result1" transform="matrix(1 0 0 1 249.5817 41.9174)">
        <rect id="twdCanvas" x="7.3" y="9.32" class="st0" width="263.03" height="72"/>
        <!-- all the texts will be canged -->
        <text id="twdWeekdayshorttext" transform="matrix(1 0 0 1 249.5817 41.9174)"><tspan x="0" y="0" class="st2 st3">C</tspan><tspan x="-1.2" y="29.13" class="st2 st3">S</tspan></text>
        <text id="twdDatenumber" transform="matrix(1 0 0 1 41.5544 69.5698)" class="st5 st6">26</text>
        <line id="twdDivider" class="st7" x1="126.49" y1="9.32" x2="126.49" y2="81.32"/>
        <g id="twdText">
            <text id="twdTextLine3" transform="matrix(1 0 0 1 135.0475 28.1718)" class="st2 st8">changed this</text>
            <text id="twdTextLine2" transform="matrix(1 0 0 1 135.0475 41.5319)" class="st2 st8">changed this</text>
            <text id="twdTextLine1" transform="matrix(1 0 0 1 135.0475 54.892)" class="st2 st8">changed this</text>
            <text id="twdTextLine0" transform="matrix(1 0 0 1 135.0475 68.252)" class="st2 st8">changed this</text>
        </g>
        <line id="twdDateNumAliignerLeft" class="st0" x1="120.02" y1="17.39" x2="120.02" y2="72.07"/>
        <rect id="twdBoxText" x="132.49" y="17.39" class="st0" width="107.92" height="54.68"/>

        <!-- this: <rect id="twdBoxStar" x="15.68" y="19.75" class="st0" width="21" height="21"/> to: -->
        <use x="132.49" y="17.39" width="21" height="21" xlink:href="#Star" /><!-- how can I chnage the fill color? -->

        <!-- this: <rect id="twdBoxMoon" x="15.68" y="49.15" class="st0" width="21" height="21"/> to: -->
        <use x="15.68" y="49.15" width="21" height="21" xlink:href="#MoonFull" />
    </g>
    <!-- and so on... the end I have to adjust the viewbox and resolution-->
</g>
</svg>

推荐答案

修改现有结构

$svg_data = <<<'SVG'
<svg xmlns:svg="http://www.w3.org/2000/svg">
  <svg:style>
    circle { fill: orange; stroke: black; }
  </svg:style>
  <svg:g id="group-a" stroke="green" fill="white" stroke-width="5">
     <circle cx="25" cy="25" r="15"/>
     <circle cx="40" cy="25" r="15"/>
  </svg:g>
  <svg:g id="group-b" stroke="red" fill="blue" stroke-width="1">
     <circle cx="10" cy="80" r="15"/>
  </svg:g>
</svg>
SVG;

$svgTemplate = new SimpleXMLElement($svg_data);
$svgTemplate->registerXPathNamespace('svg', 'http://www.w3.org/2000/svg');

// How to retrieve the style string
$style = $svgTemplate->xpath('svg:style');
printf("Original style:\n%s\n\n", (string)$style[0]);

// How to set the style string
$children = $svgTemplate->children('svg', true);
$children->style = '/* new style */';

// How to copy a group and change attributes on it (like translate x and y)
$group_a = $svgTemplate->xpath('svg:g[@id="group-a"]');
if (isset($group_a[0])) {
  $group_a[0]->addAttribute('transform', 'translate(30) rotate(45 50 50)');
}

printf("Modified XML:\n%s\n", $svgTemplate->asXML());

输出

Original style:

    circle { fill: orange; stroke: black; }


Modified XML:
<?xml version="1.0"?>
<svg xmlns:svg="http://www.w3.org/2000/svg">
  <svg:style>/* new style */</svg:style>
  <svg:g id="group-a" stroke="green" fill="white" stroke-width="5" transform="translate(30) rotate(45 50 50)">
     <circle cx="25" cy="25" r="15"/>
     <circle cx="40" cy="25" r="15"/>
  </svg:g>
  <svg:g id="group-b" stroke="red" fill="blue" stroke-width="1">
     <circle cx="10" cy="80" r="15"/>
  </svg:g>
</svg>

说明

通过SimpleXMLElement对象> casting 到字符串.这是可能的,因为SimpleXMLElement实现了__toString方法.

The node values are fetched by means of casting of the SimpleXMLElement object to string. This is possible because SimpleXMLElement implements __toString method.

由于children方法通过引用返回节点对象,因此可以通过修改此方法返回的值来修改原始结构.请注意,您应该在适当的时候将注册的名称空间传递给children方法.

Since the children method returns the node objects by reference, you can modify the original structure by modifying the value returned by this method. Note, you should pass the registered namespace to the children method when appropriate.

要添加属性,您需要获取节点(例如,使用xpath方法)并在该节点的上下文中调用addAttribute方法.

In order to add an attribute you need to fetch the node (using xpath method, for instance) and call addAttribute method in context of this node.

SimpleXMLElement(例如,xpathchildrenattributes)的方法返回一组匹配的元素作为SimpleXMLElement对象.您可以按索引(例如$style[0])或按名称($children->style)访问它们.您也可以使用foreach对其进行迭代.

The methods of SimpleXMLElement (xpath, children, and attributes, for instance) return a set of matching elements as SimpleXMLElement objects. You can access them either by index (e.g. $style[0]), or by name ($children->style). You can also iterate them using foreach.

据我所知,如果不手动进行深度复制,则不可能将SimpleXMLElement节点附加到文档中.您可以通过递归迭代节点并调用addChild方法来制作深层副本.但是有一种使用DOM扩展名执行此操作的简单方法:

As far as I can see, it is impossible to append a SimpleXMLElement node to the document without doing the deep copy manually. You can make a deep copy by iterating the nodes recursively and calling the addChild method. But there is an easy way to perform this using the DOM extension:

$svg = new SimpleXMLElement($svg_data);
$svg->registerXPathNamespace('svg', 'http://www.w3.org/2000/svg');

$g_tpl = $svg->xpath('svg:g[@id="TemplateForm"]');
if (!isset($g_tpl[0])) {
  die("#TemplateForm group not found\n");
}

$g_res = clone $g_tpl[0];
$g_res['id'] = 'result';

$g_twd = $g_res->g[0];
$g_twd['id'] = 'result1';
$g_twd['transform'] = 'matrix(1 0 0 1 249.5817 41.9174)';

// Change the rest of the nodes in similar manner.
// Then add $g_res to the root node. You will need DOM extension for this.
$dom_res = dom_import_simplexml($g_res);
$dom_svg = dom_import_simplexml($svg);
$dom_svg->appendChild($dom_res);

echo $svg->asXML();

考虑使用DOM扩展

通常,如果您需要在相对较小的文档(例如SVG)上执行复杂的DOM操作,请使用DOM扩展而不是SimpleXML.

Consider Using DOM Extension

Generally, if you need to perform complex DOM manipulations on relatively small documents (such as SVG), use DOM extension instead of SimpleXML.

示例

$doc = new DOMDocument;
$doc->loadXML($svg_data);
$xpath = new DOMXPath($doc);
$xpath->registerNamespace('svg', 'http://www.w3.org/2000/svg');

$g_res = $doc->createElement('g');
$g_res->setAttribute('id', 'result');

$g_twd_list = $xpath->query('svg:g[@id="TemplateForm"]/svg:g[@id="twd"]');

$g_twd = clone $g_twd_list[0];
$g_twd->setAttribute('id', 'result1');
$g_twd->setAttribute('transform', 'matrix(1 0 0 1 249.5817 41.9174)');
$g_res->appendChild($g_twd);

$doc->firstChild->appendChild($g_res);
echo $doc->saveXML();

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

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