如何正确引用svg中的外部svg文件?

时间:2011-08-27 14:01:42

标签: xml svg reference element

您好我正在制作svg / js地图,其中包含许多小svg图形(城区)。我将每个图形放入一个自己的文件中,这样我的主svg文件仍然可以维护而不会膨胀。

如何正确引用其他svg的外部svg文件?

预期结果:在浏览器中打开1.svg并看到一个蓝色矩形。 它应该如何运作:w3c: use element

所以这就是我的尝试: 1.svg:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?xml-stylesheet href="style.css" type="text/css"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-       20010904/DTD/svg10.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"    width="1000" height="1000">
<use xlink:href="another.svg#rectangle"/>
</svg>

another.svg:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-       20010904/DTD/svg10.dtd">
<svg id="rectangle" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"    width="1000" height="1000">
<rect class="blue" x="558.5" y="570" width="5" height="5" />
</svg>

的style.css

.blue { fill: blue; }

结果:

  • Firefox:一个蓝色矩形(正是我想要的)
  • Chrome: Nothing
  • Opera:黑色矩形

注意:我尝试使用图像元素,但是没有使用样式表,即我有一个黑色矩形而不是蓝色矩形。

重要提示:当您想引用另一个SVG 希望将引用的SVG作为正式文档结构的一部分时,您可以use AJAX到那样做。

https://bugs.webkit.org/show_bug.cgi?id=12499

4 个答案:

答案 0 :(得分:9)

从SVG规范中定义您linked to

  

CSS2选择器不能应用于(概念上)克隆的DOM树   因为它的内容不是正式文件结构的一部分。

这意味着1.svg中的选择器不适用于克隆的DOM树。

那么为什么不简单地从another.svg引用样式表呢?这应该适用于所有浏览器,同时适用于<use><image>

另一种选择是在主svg文档(1.svg)中设置<use>元素的样式,因为样式也从那里级联到克隆树。

答案 1 :(得分:8)

这回答了原始问题,但也试图从更广泛的角度回答在SVG中引用外部SVG文件的问题。

缺乏SVG支持

六年后, Chrome和Safari仍然不允许引用/加载外部SVG文件

这就是为什么<use xlink:href="another.svg#rectangle" class="blue"/>适用于Firefox,但不适用于WebKit浏览器。

全部在一个文件中

如果项目可以负担得起,只需将所有SVG文件放在一个父HTML或SVG文件中即可。这样,它可以在所有三种浏览器中运行:

然而,它不是外在的,被授予!

要从缓存中受益并避免重复自己,我们希望将可重复的SVG内容保存在外部文件中。

解决方法:通过JavaScript插入外部SVG文件

将样式和定义保存在一个SVG文件中,将SVG几何体保存在其他文件中,然后通过JavaScript从后者加载前者。

纯SVG和纯JavaScript

定义我们希望能够使用的内容。 styles-and-defs.svg

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <style type="text/css" >
    <![CDATA[

    .blue { fill: blue; }

    ]]>
    </style>

    <defs>
        <rect id="rectangle" class="blue" width="50" height="50" />
    </defs>
</svg>

使用上面创建的几何体,并加载其定义。 parent.svg

<svg version="1.1"
    baseProfile="full"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    xmlns:ev="http://www.w3.org/2001/xml-events"
    width="420" height="120">

    <use xlink:href="#rectangle" x="10" y="10" />

    <script><![CDATA[

        /** When the document is ready, this self-executing function will be run. **/
        (function() {

            var ajax = new XMLHttpRequest();
            ajax.open("GET", "styles-and-defs.svg", true);
            ajax.send();

            /**
             * Append the external SVG to this very SVG.
             *
             * Notice the use of an SVG selector on the document derived from the AJAX result.
             *  This is because the full document cannot be included directly into the SVG.
             *  Trying to include to do so would result in:
             *      `HierarchyRequestError: Node cannot be inserted at the specified point in the hierarchy` in Firefox;
             *      `Nodes of type '#document' may not be inserted inside nodes of type 'svg'.` in Chrome.
             */
            ajax.onload = function(e) {
                var parser = new DOMParser();
                var ajaxdoc = parser.parseFromString( ajax.responseText, "image/svg+xml" );
                document.getElementsByTagName('svg')[0].appendChild( ajaxdoc.getElementsByTagName('svg')[0] );
            }

        })();   /* END (anonymous function) */

    ]]></script>
</svg>

这回答了OP。

在HTML

与纯SVG相同的基本方法:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>
        Load external SVG (HTML)
    </title>
    <meta name="author" content="Fabien Snauwaert">
</head>

<body>

    <svg version="1.1"
    baseProfile="full"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    xmlns:ev="http://www.w3.org/2001/xml-events"
    width="420" height="120">
        <use xlink:href="#rectangle" x="10" y="10"  />
    </svg>

<script>

    /** When the document is ready, this self-executing function will be run. **/
    (function() {

        var ajax = new XMLHttpRequest();
        ajax.open("GET", "styles-and-defs.svg", true);
        ajax.send();

        /**
         * Append the external SVG to this very SVG.
         *
         * Notice the use of an SVG selector on the document derived from the AJAX result.
         *  This is because the full cannot be included directly into the SVG.
         *  Trying to include to do so would result in:
         *      `HierarchyRequestError: Node cannot be inserted at the specified point in the hierarchy` in Firefox;
         *      `Nodes of type '#document' may not be inserted inside nodes of type 'svg'.` in Chrome.
         */
        ajax.onload = function(e) {
            var parser = new DOMParser();
            var ajaxdoc = parser.parseFromString( ajax.responseText, "image/svg+xml" );
            document.getElementsByTagName('body')[0].appendChild( ajaxdoc.getElementsByTagName('svg')[0] );
        }

    })();   /* END (anonymous function) */

</script>

</body>
</html>

你当然可以使用jQuery(或者为什么不是优秀的D3.js)来加载文件。

说明

  • 注意使用<defs>。我相信这是一个关于拥有外部SVG的好处,你可以保持一切整洁有序。 (如果没有它,我们将两次显示内容。)
  • 我摆脱了style.css并简单地将CSS放在了styles-and-defs文件中。
  • 如果在HTML版本中,您观察到父SVG与窗口边界之间存在间隙,这是因为&#34;不可见&#34;与任何其他SVG一样,SVG(具有样式和定义)是inline元素。要摆脱这个差距,只需在该SVG上设置style="display: block;"
  • Download all examples here

SVG很棒但是看起来支持得太少了,而它确实允许一些很棒的东西。我希望这可以帮助一些人。

在OS X 10.12.6上的测试OK:

  • Firefox 59.0.2
  • Chrome 66.0.3359.139
  • Safari 11.0.1

答案 2 :(得分:3)

尝试这样做:

广场:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"    width="1000" height="1000">
    <rect x="558.5" y="570" width="5" height="5" id="rectangle" />
</svg>

使用它:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?xml-stylesheet href="style.css" type="text/css"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"    width="1000" height="1000">
    <use xlink:href="another.svg#rectangle" class="blue"/>
</svg>

答案 3 :(得分:0)

<svg>元素没有xlink:href属性,如果您需要包含外部图片,请使用<image>元素。