所以我有一个THREE.js场景,我必须取消将文件上传到场景。在我的页面中,我可以上传多个可能的文件,但我尝试设置它,以便您一次只能上传一个文件以便在场景中查看。我使用angular来实现我的三个js场景和画布本质上是一个工厂,因为我一次只想要一个画布的一个实例。这是该工厂的基本代码(对于这个特定问题)我顺便使用Angular,这是开始时app.factory和PartLibrary注入的原因,但这不是相关。您需要知道的是PartLibrary.load_part_stl()只是一个函数,它调用ajax来获取要加载的stl文件的url ::
app.factory('ModelViewer', ['PartLibrary', function(QuoteLibrary){
var modelViewer = {
model_material: {},
part_model: {},
part: {},
scene: {},
camera: {},
renderer: {},
loader: {},
manager: {},
id: {}
};
modelViewer.destroy_old = function(canvas_selector){
cancelAnimationFrame(this.id);
this.scene = null;
this.renderer = null;
this.camera = null;
this.part_edges = null;
this.part_model = null;
this.loader = null;
this.manager = null;
$('canvas').remove();
}
modelViewer.init = function(part, canvas_selector){
var self = this;
// distroy any old three js canvases
self.destroy_old(canvas_selector);
self.part = part;
self.initiated = true;
var container = $(canvas_selector)[0];
self.scene = new THREE.Scene();
self.camera = new THREE.PerspectiveCamera( 45, $(canvas_selector).width()/$(canvas_selector).height(), 1, 20000 );
self.scene.add( new THREE.AmbientLight( 0x4F4F4F ) );
self.renderer = new THREE.WebGLRenderer( { antialias: true } );
container.appendChild( self.renderer.domElement );
PartLibrary.load_part_stl(part.id)
.success(function(url){
loadModel(url, self);
})
.error(function(){
console.log("Error loading STL file for 3D view");
});
function loadModel(url){
self.manager = new THREE.LoadingManager();
self.loader = new THREE.STLLoader(self.manager);
self.manager.onLoad = function(item, loaded, total){
$('.model-loading').hide();
}
self.loader.load(url, function(geometry){
self.model_material = new THREE.MeshPhongMaterial();
self.part_model = new THREE.Mesh( geometry, self.model_material );
self.scene.add( self.part_model );
});
}
function animate() {
self.id = requestAnimationFrame( animate );
render();
}
function render() {
// var timer = Date.now() * 0.0005;
self.renderer.render( self.scene, self.camera );
}
animate();
}
return modelViewer;
}]);
所以基本上它是如何工作的是有多个可能的画布(取决于canvas_selector),但只有一个活动画布,因为旧的画布/场景/渲染器/等...每次启动新模型时都会被销毁(因此init函数开头的self.destroy_old)。
如果我在创建新场景之前等待加载对象,它会按预期工作,因此当启动新场景时,场景中只会出现一个部分。但是,如果启动场景,然后在旧场景仍在加载该部分时启动另一场景,则新场景将加载新旧场景。尽管在创建新的之前将loader,loadermanager和part设置为null,但仍会发生这种情况。
那么有人知道如何阻止加载器在加载时将文件加载到场景中吗?
我无法在文档中找到任何看似加载器或STLLoader(继承加载器)的本机函数。
答案 0 :(得分:1)
现在只是为了更新任何人,拉取请求已经合并,你可以在onprogress回调中实际取消。
var loader = new THREE.STLLoader();
loader.load('test.stl', function ( geometry ) {
//stuff here
}, function(url) {
//logic here
url.currentTarget.abort()
}) ;
答案 1 :(得分:0)
好的,所以我必须对three.js和STLLoader文件进行一些(非常简单的)更改,我从这里得到了这个想法cancel download jsonLoader & ImageUtils.loadTexture。无论如何,这是我自己的解决方案:
在three.js中,我必须对THREE.XHRLoader进行以下更改:
THREE.XHRLoader.prototype = {
constructor: THREE.XHRLoader,
load: function ( url, onLoad, onProgress, onError ) {
...
var request = new XMLHttpRequest();
...
scope.manager.itemStart( url );
return request; // I ADDED THIS
},
...
};
然后在STLLoader.js中我添加了:
THREE.STLLoader.prototype = {
constructor: THREE.STLLoader,
load: function ( url, onLoad, onProgress, onError ) {
var scope = this;
var loader = new THREE.XHRLoader( scope.manager );
loader.setCrossOrigin( this.crossOrigin );
loader.setResponseType('arraybuffer');
// Here I added request to equal loader since i made load return the original xmlhttprequest
var request = loader.load( url, function ( text ) {
onLoad( scope.parse( text ) );
}, onProgress, onError );
// here I return the request further back to my own application
return request;
},
最后在我自己的代码中:
var modelViewer = {
request: {},
...
}
modelViewer.destroy_old = function(canvas_selector){
if (!$.isEmptyObject(this.request)){
this.request.abort();
}
...
}
modelViewer.init = function(part, canvas_selector){
...
function loadModel(url){
...
self.request = self.loader.load(url, function(geometry){
...
}
}
}