如何在HTML页面中加载SVG节点?

3

我有一个HTML5页面和多个声明SVG图像节点(元素)的文件。 这些文件看起来像这样:

<g class="background">
    <g class="bg_path_a">
        <path d="M0 40 L21 40" />
    </g>
    <g class="bg_path_b">
        <path d="M42 21 L63 0 100 0 M23 40 L48 15" />
    </g>
    <g class="bg_path_c">
        <path d="M53 40 L100 40 M21 40 L53 40" />
    </g>
    <g class="bg_lockpath">
        <path d="M21 40 L33 40" />
    </g>
    <g class="bg_label">
        <rect x="0" y="20" width="10" height="10" />
    </g>
</g>

没有xmlns,也没有声明DTD,应该保持这种状态。现在我希望能够加载这些文件,但在HTML5页面中以SVG图像的形式显示它们,所有操作都应在客户端运行,不允许使用服务器端脚本。

3个回答

4
<script>
function createXMLHttpRequest()
{
  if (window.XMLHttpRequest) // Firefox and others
  {
   return new XMLHttpRequest();
  }
  else if (window.ActiveXObject) // Internet Explorer
  {
    return new ActiveXObject("Microsoft.XMLHTTP");
  }
  else
  {
    alert("XMLHttpRequest not supported");
    return null;
  }
}

function fixSVG()
{
    var svgElement, xmlHTTP, svgDoc
    xmlHTTP = createXMLHttpRequest();
    xmlHTTP.open("GET", "BadSVG.svg", false);
    xmlHTTP.send();
    svgDoc = xmlHTTP.responseText;
    svgElement = document.getElementById("yuck");
    svgElement.outerHTML = "<svg xmlns='http://www.w3.org/2000/svg'" +
            " width='" + svgElement.width + 
            "' height='" + svgElement.height + "'>" +
            svgDoc + "</svg>";
}
</script>
[...]
<body onLoad="fixSVG()">
[...]
<embed id="yuck" src="" type="image/svg+xml"
    width="500" height="500" wmode="transparent"/>

仅在Firefox中进行测试...

如果您的文件很小,同步加载文件不应该成为问题,就像您所展示的那样。

[编辑] 小改进:避免两次加载文件(在embed标签中使用空的src),并在声明中使用embed元素的尺寸。


这当然是一个不错的解决方案,而且显然也解决了我看到的命名空间问题! - Thomas W
嗯,我正在使用Chrome ver. 23 进行测试,在函数fixSVG()中当浏览器尝试执行xmlHTTP.send()时,会出现“跨域请求仅支持HTTP”的错误。也许如果我设置一个服务器,这个问题就可以解决...但是是否有完全基于客户端的解决方案呢? - StaticBug
是的,Chrome不想使用文件协议进行XHR,我遇到了同样的问题,一旦我运行了一个服务器并使用localhost,问题就解决了。Firefox没有那么挑剔...我不理解“完全基于客户端”的问题,它已经全部“基于客户端”,即它不涉及服务器端脚本,只是使用服务器来...提供文件。 - PhiLho
抱歉之前表述不清,我的意思是我不想设置服务器,我希望用户可以在没有任何服务器的情况下使用页面并选择要加载的文件。但如果我使用chrome并加上“ --allow-file-access-from-files ”这个参数,那么它可以正常工作。谢谢。 - StaticBug

2
主要问题似乎是将SVG片段放入SVG命名空间中。您可以使用XSLT来“完成”SVG(添加周围的svg元素)并将所有内容放在正确的命名空间中:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="http://www.w3.org/2000/svg" version="1.0">

  <!-- The dimension can be supplied using a parameter.
       This defaults to 100%. -->
  <xsl:param name="width"  select="'100%'"/>
  <xsl:param name="height" select="'100%'"/>

  <xsl:template match="/">
    <svg version="1.1" width="{$width}" height="{$height}">
      <xsl:apply-templates/>
    </svg>
  </xsl:template>

  <xsl:template match="*">
    <xsl:element name="{local-name()}" namespace="http://www.w3.org/2000/svg">
      <xsl:apply-templates select="node()|@*"/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="@*|text()">
    <xsl:copy-of select="."/>
  </xsl:template>
</xsl:stylesheet>

您需要使用AJAX加载样式表和SVG片段。

使用AJAX获取SVG片段,例如:

var loadXML = function(fileName,mime) {
  xmlHttpRequest = new XMLHttpRequest()
  xmlHttpRequest.open("GET",fileName,false);
  xmlHttpRequest.send("");
  return xmlHttpRequest.responseXML;
}
var svgSnippet = loadXML(snippetURL,"image/svg+xml")
var xslt = loadXML(xsltURL,"application/xslt+xml")
var xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(xslt);
// You can override the default width/height parameters here
xsltProcessor.setParameter(null,"width","150px")
xsltProcessor.setParameter(null,"width","90px")
// In the document there must be some element to append the SVG
documentGetElementById("svgContainer").appendChild(xsltProcessor.transformToFragment(svgSnippet,document).firstChild)

以下是未经测试的内容,但可能是一个开始。如果您还需要XLink命名空间,则这当然仍然不完整。


0

如果您乐意使用jQuery,您可能想要查看Keith Wood的SVG插件。我以前用过它,非常多才多艺。

如果您查看文档页面上的“加载”选项卡,它描述了如何加载外部文件并将其添加到现有的SVG中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接