jjzjj

xml - 如何在 SVG 中正确引用外部 SVG 文件?

coder 2024-06-23 原文

你好,我正在制作 SVG/JS map ,它由许多小的 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>

另一个.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>

样式.css

.blue { fill: blue; }

结果:

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

注意:我尝试使用图像元素,但它不适用于样式表,即我得到的是黑色矩形而不是蓝色矩形。

重要:当您想要引用另一个 SVG 并且希望引用的 SVG 成为正式文档结构的一部分时,您可以 use AJAX这样做。

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

最佳答案

这回答了最初的问题,但也试图从更广泛的角度回答在 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 和窗口边框之间存在间隙,这是因为“不可见”SVG(具有样式和定义)与任何其他 SVG 一样,是一个 inline。元素。要消除这个差距,只需设置 style="display: block;"在那个 SVG 上。
  • Download all examples here .

SVG 很棒,但支持的似乎太少,但它确实允许做一些很棒的事情。我希望这对那里的一些人有所帮助。

在 OS X 10.12.6 上测试正常:

  • Firefox 59.0.2
  • Chrome 66.0.3359.139
  • Safari 11.0.1

关于xml - 如何在 SVG 中正确引用外部 SVG 文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7215009/

有关xml - 如何在 SVG 中正确引用外部 SVG 文件?的更多相关文章

  1. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  2. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  3. ruby - 如何在 Ruby 中顺序创建 PI - 2

    出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits

  4. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  5. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  6. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  7. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  8. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  9. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  10. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

随机推荐