SVG片段被错误地解析为HTMLUnknownElement

时间:2011-05-20 16:46:28

标签: javascript jquery svg

使用Javascript编写内联SVG时遇到问题 问题可以简化为以下代码(live example here):

身体内某处:

<svg id="drawing" xmlns="http://www.w3.org/2000/svg" version="1.1">
</svg>

在onReady内部:

$("#drawing").append($("<rect style='fill: blue' width='100' height='100' />"));

我希望现在看到一个蓝色矩形。但是,Chrome和Firefox不会显示任何内容。

使用Firebug,我发现Firefox将“rect”解释为HTMLUnknownElement(而不是SVGElement)。 如果我在SVG元素上选择“编辑SVG”(使用Firebug)并在某处插入空格,则SVG似乎会被重新分析并显示矩形。

如何告诉解析器正确解析这个片段?

4 个答案:

答案 0 :(得分:1)

我担心这不容易:

  1. jsfiddle不是测试svg的地方,它发送错误的内容类型
  2. 无法通过html-way创建对外部js文件的引用(始终牢记,svg不必对html执行任何操作)
  3. jquery在使用append()时使用一些dummy-div来创建元素,但是svg不知道div元素
  4. 还要注意:使用jQuery绑定到svg文档的load-event似乎不起作用
  5. 这里有一个示例代码,在作为image / svg + xml

    传递时适用于FF
    <svg id="drawing" 
         xmlns="http://www.w3.org/2000/svg" 
         xmlns:xlink="http://www.w3.org/1999/xlink"
         version="1.1"  
         onload="fx()">
      <script type="text/ecmascript" xlink:href="http://code.jquery.com/jquery-latest.js" />
      <script type="text/ecmascript">
      function fx()
      {
       $(document.createElementNS('http://www.w3.org/2000/svg', 'rect'))
         .css('fill','blue')
         .attr({'width':100,'height':100})
         .appendTo('#drawing');
       }
      </script>  
    </svg>
    

    但是和Marcin一样,我建议使用插件。

    要从父文档添加,您可以使用包含元素属性的对象,基本示例:


    <html>
    <head>
    <script src="http://code.jquery.com/jquery-latest.js"></script>
    <script  type="text/javascript">
    /*<![CDATA[*/
    
    function fx(obj,params)
    {
      var svgDoc=obj.contentDocument;
      if(typeof params.name!='string')return;
      var props=$.extend({'attrs':{},'style':{},'selector':null},params);
          props.target=(!props.selector)?svgDoc.documentElement:$(svgDoc).find(props.selector)
    
        $(svgDoc.createElementNS('http://www.w3.org/2000/svg', props.name))
         .css(props.style)
         .attr(props.attrs)
         .appendTo(props.target);
    }
    
    /*]]>*/
    </script>
    </head>
    <body>
      <object onload="fx(this,{'name':'rect','attrs':{'width':100,'height':100},'style':{'fill':'blue'},'selector':'#drawing'})" 
              data="my.svg" 
              type="image/svg+xml" 
              width="200" 
              height="200">
        <param name="src" value="my.svg">
      </object>
    </body> 
    </html>
    

    对象的结构:

    • 名:的tagName(字符串)
    • ATTRS:属性(对象)
    • 样式:样式(对象)
    • selector:selector(字符串,如果省略,将选择root元素)

答案 1 :(得分:1)

此示例显示如何在XHTML中嵌入SVG,包括以编程方式创建新的SVG元素:http://phrogz.net/svg/svg_in_xhtml5.xhtml

此示例显示如何使用XHR将SVG作为XML获取,查找其片段,以及在将节点附加到现有SVG文档之前将其转换为本地文档的两种方式:http://phrogz.net/svg/fetch_fragment.svg

一般来说:

  1. 不要直接使用jQuery和SVG。
  2. 必须使用createElementNS创建动态创建的SVG元素,并提供SVG名称空间URI 'http://www.w3.org/2000/svg'。 (但请注意,不应使用命名空间创建SVG属性。)
  3. 您需要确保以XML格式提供XHTML(内容类型:application / xhtml + xml)而不是text / html。
  4. 这是我偶尔用来创建SVG元素的通用函数。它既适用于SVG文档,也适用于SVG-in-XHTML,允许直接创建文本内容,并支持命名空间属性(例如xlink:href)。

    // Example usage:
    //   var parentNode = findElementInTheSVGDocument();
    //   var r = createOn( parentNode, 'rect', {
    //     x:12, width:10, height:10, 'fill-opacity':0.3
    //   });
    function createOn(root,name,attrs,text){
      var doc = root.ownerDocument;
      var svg = root;
      while (svg.tagName!='svg') svg=svg.parentNode;
      var svgNS = svg.getAttribute('xmlns');
      var el = doc.createElementNS(svgNS,name);
      for (var attr in attrs){
        if (attrs.hasOwnProperty(attr)){
          var parts = attr.split(':');
          if (parts[1]) el.setAttributeNS(svg.getAttribute('xmlns:'+parts[0]),parts[1],attrs[attr]);
          else el.setAttributeNS(null,attr,attrs[attr]);
        }
      }
      if (text) el.appendChild(document.createTextNode(text));
      return root.appendChild(el);
    } 
    

答案 2 :(得分:0)

我假设您希望获得一个解析SVG的片段,而不必将其转换为JSON等等。这是一些做它的CoffeeScript。我在嵌入HTML的SVG上测试了代码,但我认为它应该适用于任何情况。

https://github.com/pwnall/ddr/blob/master/javascripts/graphics/pwnvg.coffee#L169

我将SVG片段包装在一个标签中以构建一个独立的SVG文档,然后我使用DOMParser来解析SVG文档,然后逐个拉出根元素(包装器)的子元素,并且将它们粘贴到原始SVG的DOM中。

理论上讲,有一种更简单(更快速的方法),但它现在不起作用。 http://crbug.com/107982

答案 3 :(得分:0)

请参阅:Convert svg into base64

我总是确保svg片段在svg元素内部或者只是强制刷新svg。