Использование трех в классе ECMA Script 6 STL Viewer
Я пытаюсь преобразовать демонстрацию Three STL Viewer в класс ES6, который затем компилируется с webpack 2, но я хочу, чтобы он открывал файл по URL, а не по фактическому вводу файла, мне удалось загрузить три компонента и большую часть класс работает, но я думаю, что у меня есть проблемы в области видимости с несколькими компонентами, я столкнулся с проблемой, которую я, кажется, не могу решить, пытаясь использовать FileReader и затем открывая сцену и объект. TypeError: Cannot read property 'remove' of undefined
threeDimensionalModels.js
// jshint esversion:6
import {
Scene, PerspectiveCamera, WebGLRenderer, Geometry, Mesh,
AmbientLight, DirectionalLight, MeshPhongMaterial, Vector3, Face3,
} from 'three';
var thisClass = null;
class threeDimensionalModels {
constructor(height,width,selector){
this.w = height;
this.h = width;
this.selector = selector;
this.renderer = new WebGLRenderer();
this.view = document.getElementById(this.selector);
this.camera = new PerspectiveCamera(45, this.w / this.h, 1, 1000);
this.scene = new Scene();
this.light1 = new DirectionalLight(0xffffff);
this.light2 = new DirectionalLight(0xffffff);
this.mat = new MeshPhongMaterial({ color: 0x339900, specular: 0x030303 });
this.obj = new Mesh(new Geometry(), this.mat);
this.renderer.setSize(this.w, this.h);
this.view.appendChild(this.renderer.domElement);
this.camera.position.set(0, 0, 50);
this.scene.add(new AmbientLight(0x666666));
this.light1.position.set(0, 100, 100);
this.scene.add(this.light1);
this.light2.position.set(0, -100, -100);
this.scene.add(this.light2);
this.scene.add(this.obj);
}
static binaryVector3(view, offset) {
var v = new Vector3();
v.x = view.getFloat32(offset + 0, true);
v.y = view.getFloat32(offset + 4, true);
v.z = view.getFloat32(offset + 8, true);
return v;
}
static loadBinaryStl(buffer) {
// binary STL
var view = new DataView(buffer);
var size = view.getUint32(80, true);
var geom = new Geometry();
var offset = 84;
for (var i = 0; i < size; i++) {
var normal = threeDimensionalModels.binaryVector3(view, offset);
geom.vertices.push(threeDimensionalModels.binaryVector3(view, offset + 12));
geom.vertices.push(threeDimensionalModels.binaryVector3(view, offset + 24));
geom.vertices.push(threeDimensionalModels.binaryVector3(view, offset + 36));
geom.faces.push(
new Face3(i * 3, i * 3 + 1, i * 3 + 2, normal));
offset += 4 * 3 * 4 + 2;
}
return geom;
}
static m2vec3(match) {
var v = new Vector3();
v.x = parseFloat(match[1]);
v.y = parseFloat(match[2]);
v.z = parseFloat(match[3]);
return v;
}
static toLines(array) {
var lines = [];
var h = 0;
for (var i = 0; i < array.length; i++) {
if (array[i] === 10) {
var line = String.fromCharCode.apply(
null, array.subarray(h, i));
lines.push(line);
h = i + 1;
}
}
lines.push(String.fromCharCode.apply(null, array.subarray(h)));
return lines;
}
static loadTextStl(buffer) {
var lines = threeDimensionalModels.toLines(new Uint8Array(buffer));
var index = 0;
var scan = function (regexp) {
while (lines[index].match(/^\s*$/)) index++;
var r = lines[index].match(regexp);
return r;
};
var scanOk = function (regexp) {
var r = scan(regexp);
if (!r) throw new Error(
"not text stl: " + regexp.toString() +
"=> (line " + (index - 1) + ")" +
"[" + lines[index-1] + "]");
index++;
return r;
};
var facetReg = /^\s*facet\s+normal\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)/;
var vertexReg = /^\s*vertex\s+([^s]+)\s+([^\s]+)\s+([^\s]+)/;
var geom = new Geometry();
scanOk(/^\s*solid\s(.*)/);
while (!scan(/^\s*endsolid/)) {
var normal = scanOk(facetReg);
scanOk(/^\s*outer\s+loop/);
var v1 = scanOk(vertexReg);
var v2 = scanOk(vertexReg);
var v3 = scanOk(vertexReg);
scanOk(/\s*endloop/);
scanOk(/\s*endfacet/);
var base = geom.vertices.length;
geom.vertices.push(threeDimensionalModels.m2vec3(v1));
geom.vertices.push(threeDimensionalModels.m2vec3(v2));
geom.vertices.push(threeDimensionalModels.m2vec3(v3));
geom.faces.push(
new Face3(base, base + 1, base + 2, threeDimensionalModels.m2vec3(normal)));
}
return geom;
}
static loadStlModel(buffer) {
try {
return threeDimensionalModels.loadTextStl(buffer);
} catch (ex) {
return threeDimensionalModels.loadBinaryStl(buffer);
}
}
openStl(url) {
var blob = null;
var xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.responseType = "blob";//force the HTTP response, response-type header to be blob
xhr.onload = function() {
blob = xhr.response;
thisClass = this;
var reader = new FileReader();
reader.addEventListener("load", function (ev) {
var buffer = ev.target.result;
var geom = threeDimensionalModels.loadStlModel(buffer);
threeDimensionalModels.scene.remove(thisClass.obj);
threeDimensionalModels.obj = new Mesh(geom, threeDimensionalModels.mat);
threeDimensionalModels.scene.add(threeDimensionalModels.obj);
}, false);
reader.readAsArrayBuffer(blob);
};
xhr.send();
}
}
export default threeDimensionalModels;
HTML
<div id="threedm-view"></div>
<script type="text/javascript">
window.addEventListener("load", function () {
"use strict";
var threedm = new threeDimensionalModels(800,800,'threedm-view');
var loop = function loop() {
requestAnimationFrame(loop);
threedm.obj.rotation.z += 0.05;
threedm.renderer.clear();
threedm.renderer.render(threedm.scene, threedm.camera);
};
loop();
threedm.openStl("/app/uploads/2017/07/Stator.stl");
});
</script>
1 ответ
Немного поэкспериментировав и взглянув на проблемную область, я понял, что применяю это к глобальной переменной, где этого в контексте, которого я хотел, не существует, я хотел бы найти лучший способ передачи этого в дочерние функции внутри функций класса ECMA без использования глобальной переменной
Обновить
class threeDimensionalModels {
// .... //
openStl(url) {
var blob = null;
var xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.responseType = "blob";
thisClass = this; // Moved from inside xhr.onload
xhr.onload = function() {
blob = xhr.response;
var reader = new FileReader();
reader.addEventListener("load", function (ev) {
var buffer = ev.target.result;
var geom = threeDimensionalModels.loadStlModel(buffer);
thisClass.scene.remove(thisClass.obj);
thisClass.obj = new Mesh(geom, thisClass.mat);
thisClass.scene.add(thisClass.obj);
}, false);
reader.readAsArrayBuffer(blob);
};
xhr.send();
}
// ... //
}