首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在svg中正确引用外部svg文件?

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

Stack Overflow用户
提问于 2011-08-27 22:01:42
回答 4查看 37K关注 0票数 24

您好,我正在处理一个svg/js地图,其中包含许多小svg图形(城市地区)。我将每个图形放到一个自己的文件中,这样我的主svg文件仍然是可维护的,不会臃肿。

如何从另一个svg正确引用外部svg文件?

预期结果:在浏览器中打开1.svg并看到一个蓝色矩形。它的工作原理:w3c: use element

所以我试了一下: 1.svg:

代码语言:javascript
复制
<?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:

代码语言:javascript
复制
<?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

代码语言:javascript
复制
.blue { fill: blue; }

结果:

  • Firefox:一个蓝色矩形(就是I wanted)
  • Chrome:Nothing
  • Opera: rectangle

注意:我尝试过使用image元素,但在样式表中不起作用,即我得到了一个黑色的矩形,而不是蓝色的矩形。

重要提示:当您想要引用另一个SVG并且想要将引用的SVG作为正式文档结构的一部分时,您可以使用use AJAX来实现。

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

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2018-05-03 18:42:00

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

缺少SVG支持

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

这就是为什么<use xlink:href="another.svg#rectangle" class="blue"/>可以在火狐中工作,而不能在WebKit浏览器中工作。

所有内容都在一个文件中

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

但话说回来,它并不是真正的外部,承认吧!

为了从缓存中获益并避免重复,我们希望将可重复的内容保存在外部文件中。

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

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

纯SVG和纯JavaScript

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

代码语言:javascript
复制
<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

代码语言:javascript
复制
<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>

这就回答了这个问题。

在HTML中

与纯SVG相同的基本方法:

代码语言:javascript
复制
<!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放在样式和定义文件中。
  • 如果在HTML版本中,您观察到父SVG和窗口边框之间有一个间隙,这是因为“看不见”的SVG (带有样式和定义)像任何其他SVG一样,是一个inline元素。要消除这种差距,只需在该SVG.
  • Download all examples here.

上设置style="display: block;"

SVG很棒,但可能看起来支持得太少,而它确实允许一些很棒的事情。我希望这能对一些人有所帮助。

在OS X 10.12.6上测试正常:

59.0.2

  • Chrome 66.0.3359.139

  • Safari 11.0.1
  • Firefox
票数 11
EN

Stack Overflow用户

发布于 2011-08-30 02:13:23

根据您linked to的SVG规范中的定义:

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

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

那么为什么不直接引用another.svg中的样式表呢?这应该适用于所有浏览器,并且适用于<use><image>

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

票数 9
EN

Stack Overflow用户

发布于 2011-08-30 02:14:53

试着这样做:

正方形:

代码语言:javascript
复制
<?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>

使用它:

代码语言:javascript
复制
<?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
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7215009

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档