如何正确解释外部SVG文件以与two.js一起使用?

时间:2014-04-13 09:04:57

标签: javascript svg two.js

如果对象标签不是真的合适,那么抓住SVG文件并使用two.js直接操作它有更好的方法吗?或者我是否必须进入SVG并将它们内联添加?

使用this question的代码和我自己的一些编辑,我无法轮换我的对象,Chrome会给我错误:未捕获TypeError:无法读取属性' x& #39;未定义的

HTML

<object type="image/svg+xml" data="./images/face.svg" id="face"></object>

JS

    $(function(){  
    var svgObject = document.getElementsByTagName('object')[0];
        svgObject.onload = function(){
            var mySvg = svgObject.contentDocument.getElementsByTagName('svg')[0];
            var two = new Two({
                fullscreen:false,
                autostart: true
            }).appendTo(document.body);
            var shape = two.interpret(mySvg);
            console.log(shape);
            two.update();
            two.bind('update', function() {
                shape.rotation += 0.01;
            });
        };
    });

由于引用问题中的代码似乎对个人有效,我假设我只是有语法错误。关于发生了什么的任何想法?

编辑:弗朗西斯&#39;帮助,我能够将我自己的SVG解析为与for循环弗朗西斯一起使用以便访问里面的元素,但它似乎正在考虑以下SVG中的嵌套G标记为null ...由于某种原因:

<svg id="svg2" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="280" width="280" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/"><g id="layer1" transform="matrix(0.99999301,0,0,1,-400.71477,-954.83987)"><g id="g3836" transform="matrix(-0.08567939,-0.08567939,0.08567939,-0.08567939,574.3717,1199.1604)"><path id="path3801" fill="#3b5998" d="m805.17-1221.6c-902.43,902.43-902.43,2365.6,0.00003,3268l517.13-517.1c-616.83-616.83-616.83-1616.9,0-2233.8z"/><path id="rect3822" fill="#FFF" d="m266.93,336.2c0.15806,60.722,23.582,102.66,103.93,102.66h44.694v62.567h71.844v-62.57h184.55v-73.089h-184.55v-62.849l-71.844-8.5959v71.445h-44.69c-20.309,0-35.863-7.2042-35.863-35.676v-38.658h-64.869c-2.0284,15.729-3.2307,30.752-3.1941,44.765z"/></g></g></svg>

此外,Chrome在加载时会引发以下错误:

&#39;未捕获的TypeError:无法读取属性&#39; nodeName&#39; of null&#39;在第68行,在handler()函数中(这是我假设嵌套的G被认为是null):

xmlDocValue.value+=XMLdoc.childNodes.item(1).nodeName +"\n"

&#39;未捕获的TypeError:无法读取属性&#39; childNodes&#39;未定义的&#39;在前面提到的for循环中,我假设是因为null元素被认为是null:

myGElems = XMLdoc.childNodes.item(0).childNodes

1 个答案:

答案 0 :(得分:0)

父html无法访问<object>的内容。我假设您要访问文件中的svg元素,并使用其nodeName和属性来创建two.js元素。如果是这样,最好的方法是使用XMLHttpRequest将svg作为XML加载,然后使用DOMParser来获取nodeName和元素的attriutes。 responseText也可以直接加载到DIV的innerHTML中。

试试这个:

创建一个名为mySVG.svg的SVG文件,如下所示:

<svg width="400" height="400" id="mySVG" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" ><circle id="myCircle"   r="100" cx="150" cy="150" fill="red" /><rect id="myRect" x="200" y="260" width="120" height="100" fill="blue" /></svg>

然后运行以下HTML文件:

   <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <title>Parse SVG Elements via XML DOM</title>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    </head>
    <body style='padding:0px;font-family:arial'>
    <center><h4>Parse SVG Elements via XML DOM</h4>
    <div style='width:90%;background-color:gainsboro;text-align:justify;padding:10px;border-radius:6px;'>
    Load svg files as XML via <b>XMLHttpRequest</b>. use <b>DOMParser</b> to parse the XML Document Element to create a client's svg elements.
    </div>
    <br />mySVG.svg:
    <textarea id=svgValue style='width:90%;height:200px;font-size:120%;font-family:lucida console;'></textarea>
    <center><b>SVG Inline</b></center>
    <div id="svgDiv" style='background-color:lightgreen;width:400px;height:400px;' ></div>
    <br /><button onClick=loadSVGXML()>load svg as xml</button><br />
    <center><b>XML Doc</b></center>
    <textarea id=xmlDocValue style='width:90%;height:100px;font-size:120%;font-family:lucida console;'></textarea>
    </center>
    <script id=myScript>
    /*
    mySVG.svg
    <svg id="mySVG"  version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" ><circle id="myCircle"   r="100" cx="150" cy="150" fill="red" /><rect id="myRect" x="200" y="260" width="120" height="100" fill="blue" /></svg>
    */
    //--onload---
    function loadSVGInline()
    {
        var SVGFile="mySVG.svg"
        var loadXML = new XMLHttpRequest;
        function handler(){
            if(loadXML.readyState == 4 && loadXML.status == 200)
            {
                svgDiv.innerHTML=loadXML.responseText
                svgValue.value=loadXML.responseText
            }
        }
        if (loadXML != null){
            loadXML.open("GET", SVGFile, true);
            loadXML.onreadystatechange = handler;
            loadXML.send();
        }
    }


/* NOTE:
If you 'hand-craft' an  svg file it may include carriage returns, or extraneous spaces between elements, the xml dom will interpret
them as #text elements, and may cause errors. Either remove carriage returns and spaces, or filter the elements
to ignore the #text elements.
*/

    var  XMLdoc
    function loadSVGXML()
    {
        var SVGFile="mySVG.svg"
        var loadXML = new XMLHttpRequest;
        function handler()
        {
            if(loadXML.readyState == 4 && loadXML.status == 200)
            {
                //---responseText---
                var xmlString=loadXML.responseText
                //---DOMParser---
                var parser = new DOMParser();
                XMLdoc=parser.parseFromString(xmlString,"text/xml").documentElement;

                xmlDocValue.value=XMLdoc.childNodes.item(0).nodeName +"\n"
                xmlDocValue.value+=XMLdoc.childNodes.item(0).getAttribute("fill") +"\n"
                xmlDocValue.value+=XMLdoc.childNodes.item(1).nodeName +"\n"
                xmlDocValue.value+=XMLdoc.childNodes.item(1).getAttribute("fill")

                //---to add xml element as svg use element.cloneNode(true)---
                var xmlNode1=XMLdoc.childNodes.item(1)
                var svgNode1=xmlNode1.cloneNode(true)
                svgNode1.setAttribute("x",20)
                svgNode1.setAttribute("fill","orange")
                mySVG.appendChild(svgNode1)
            }
        }
        if (loadXML != null){
            loadXML.open("GET", SVGFile, true);
            loadXML.onreadystatechange = handler;
            loadXML.send();
        }
    }
    </script>
    <script>
    document.addEventListener("onload",init(),false)
    function init()
    {
        loadSVGInline()
    }
    </script>
    </body>
    </html>