2017-06-05 130 views
0

我正在使用Two.js,我想让用户导入一个svg文件并将其显示在我的场景中。(JavaScript)从文件或文件读取器导入外部<object> svg对象

Two.interpret()可以采取在它SVG数据标签的任何DOM,所以我创造了这个功能从文件模拟标签:

this.m_Two.interpretFromFile = function (two, fname) { 
     //Create an object and load an svg from 'fname' 
     var object = document.createElement("object"); 
     //Set the id to the filename without path or extension 
     object.id = fname; 
     object.id = object.id.replace(/\\/g, '/'); 
     object.id = object.id.substring(object.id.lastIndexOf('/')+1, object.id.lastIndexOf('.')); 
     console.log("Importing " + object.id); 
     object.data = fname; //HTML takes care of the rest 
     object.type = "image/svg+xml"; 
     object.width = 64; //Import from file maybe? 
     object.height = 64; 
     object.style = "visibility:hidden;position:absolute;left:0px;top:0px;"; 
     document.body.appendChild(object); //Add it to the body (invis) that way it loads 
     //When it loads, finish up 
     object.onload = function() { 
      if (!object.contentDocument || object.contentDocument.getElementsByTagName("svg").length < 1) return; 
      var svgObj = object.contentDocument.getElementsByTagName('svg')[0]; 
      var ret = two.interpret(svgObj); 
      document.body.removeChild(object); //Remove it. Use path.clone to duplicate stuff.. 
      return ret; //Return our new svg path 
     } 
    }; 

此功能需要两个实例,和一个文件的url,并返回一个two.path。

当使用控制台时,这一切都可以正常工作,并且与 twoInstance.interpretFromFile(twoInstance,“images/Test.svg”);

但是,我在本地运行这些文件进行测试,我当然不希望任何人进入浏览器的控制台并使用该功能,已经知道该文件的确切路径,并且知道键入“file:/ /”这条道路...... Yeesh

document.getElementById("dWorkSpace").ondrop = function(e) { 
      e.preventDefault(); //Default event loads the file itself.. KILL IT WITH FIRE. 

      if (!e.dataTransfer || !e.dataTransfer.items.length > 0 || !e.dataTransfer.files[0]) return; 

      var file = e.dataTransfer.files[0]; 

      twoInstance.interpretFromFile(twoInstance, "file://" + file.name); 
    } 

‘file.name’只给出了文件,而不是路径(是的,我知道这是在浏览器中securety的事情了。我已经看了所有的关于这个问题的其他问题..)

因此,现在,我可以使用FileReader来读取svg文件本身,但是如何将该数据读入标签?我需要这种格式的一些点:

  <object data="Test.svg" type="image/svg+xml"></object> 

因为Two.js似乎不喜欢“SVG”标签..只是“对象”标签..

我的enlongated问题非常抱歉正如你所看到的,我在这个兔子洞里很深。我试图只使用相关的代码,但老实说,整个事情是巨大的,我不想发布一切。

+0

'twoInstance.interpretFromFile()'期望只有第二个参数的文件路径吗?数据URI是预期的参数吗?你可以设置'的结果。readAsDataURL()'''data'属性。 – guest271314

+0

基本上我只是将对象的'数据'属性设置为文件名(它是一个字符串)。所以要回答这个问题:如果它适用于的数据标签,它适用于该功能,因为这是它的全部用途。 - 神圣的废话..我知道你在说什么!这就是诀窍! –

+0

请参阅https://stackoverflow.com/help/someone-answers,https://stackoverflow.com/help/self-answer – guest271314

回答

0

您将不得不从File对象创建一个BlobURL(它只是指向用户磁盘上文件的直接指针),然后将<object>data设置为此BlobURL。

在这里,我将只使用一个<input>元素,但它基本上与任何斑点/文件,其中的一次,他们来到(不过,请注意IIRC你需要调用从dataTransfer的文件getAsFile()方法相同。

f.onchange = e =>{ 
 
    var file = f.files[0]; 
 
    if(file.type === 'image/svg+xml'){ 
 
    var obj = document.createElement('object'); 
 
    obj.data = URL.createObjectURL(file); 
 
    obj.onload = e => URL.revokeObjectURL(obj.data); 
 
    document.body.appendChild(obj); 
 
    } 
 
    }; 
 
    
<input type="file" id="f"/>

+0

这同样适用! - event.dataTranfer.files []已经是文件对象,但我使用event.dataTransfer.items [0] .getAsFile()来获得相同的结果。我认为只有items数组/对象具有getAsFile函数,并且文件数组/对象已经被转换。 –

1

什么一个快速的答案.. @ guest271314(我会联系,如果我可以在以后看着办吧)

这为我工作:

document.getElementById("dWorkSpace").ondrop = function(e) { 
    e.preventDefault(); //Default event loads the file itself.. KILL IT WITH FIRE. 

    if (!e.dataTransfer || !e.dataTransfer.items.length > 0 || !e.dataTransfer.files[0]) return; 

    var file = e.dataTransfer.files[0]; 

    var reader = new FileReader(); //Make a reader 

    reader.onloadend = function (evt) { //When the file is actually loaded 
     Application.m_Two.interpretFromFile(Application.m_Two, reader.result); 
    } 
    reader.readAsDataURL(file); 
} 

变化比特与的FileReader对象,我用readAsDataUrl像 guest271314被谈论的第一个注释。你能说我是新人吗? xD

演示:http://jonathancrowder.com/AnimatorProject/Application.html - 将SVG文件拖放到页面上进行尝试。