demo需求:移动端,实现obj本地离线浏览 结合需求,利用(vue2+threejs173)进行obj的加载,然后采用apk方式(hbuilderX打包发布)移动端浏览;
https://github.com/bianbian886/LoadLocalObjThreejs-Vue2.githttps://github.com/bianbian886/LoadLocalObjThreejs-Vue2.git
技术要点:
1、threejs的objloader的方法是使用Fetch API进行网络请求,不适用与three原生obj 的加载方式,因此需要改造three的方法;
常规通用写法:
mtlLoader.load(
"./static/models1/xpj1/A-XPJ.mtl",
function (materials) {
materials.preload();
objLoader
.setMaterials(materials)
.load("./static/models1/xpj1/A-XPJ.obj", function (object) {
object.children[0].geometry.computeBoundingBox(); //
object.children[0].geometry.center(); //定位到模型中心
console.log(object.children[0].geometry.center());
object.rotateZ(Math.PI / 2); //模型倒置
object.rotateY(Math.PI / 2); //模型倒置
object.position.y = 10; //模型抬升
that.scene.add(object);
}),
(xhr) => {
console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
},
// called when loading has errors
(error) => {
console.log("An error happened " + error);
};
}
);
}
但是在apk调试会报请求错误,因为是fecth api的方式。
解决方式:将threejs的objloader的方法改为XMLHttpRequest进行请求。代码如下:
// 加载 .mtl 文件
loadMTL(mtlLoader, mtlUrl, callback) {
const xhr = new XMLHttpRequest();
xhr.open("GET", mtlUrl, true);
xhr.onload = function () {
if (xhr.status === 200) {
const materials = mtlLoader.parse(xhr.responseText); // 解析 .mtl 文件
materials.preload(); // 预加载材质
callback(materials);
} else {
console.error("Failed to load MTL file:", xhr.statusText);
}
};
xhr.onerror = function (error) {
console.error("Error loading MTL file:", error);
};
xhr.send();
}
// 加载 .obj 文件
loadOBJ(objLoader, objUrl, materials, callback) {
const xhr = new XMLHttpRequest();
xhr.open("GET", objUrl, true);
xhr.onload = function () {
if (xhr.status === 200) {
objLoader.setMaterials(materials); // 设置材质
const object = objLoader.parse(xhr.responseText); // 解析 .obj 文件
callback(object);
} else {
console.error("Failed to load OBJ file:", xhr.statusText);
}
};
xhr.onerror = function (error) {
console.error("Error loading OBJ file:", error);
};
xhr.send();
}
var objLoader = new OBJLoader();
var mtlLoader = new MTLLoader();
this.loadMTL(mtlLoader, mtlUrl, function (materials) {
that.loadOBJ(objLoader, objUrl, materials, function (object) {
console.log("Model loaded");
// 对单个模型进行操作
const model = object.children[0];
/model.geometry.computeBoundingBox();
model.geometry.center();//模型定位
console.log(model.geometry.center());
//object.rotateZ(Math.PI);
object.rotateX(Math.PI/2);
object.scale.setScalar(0.3);
//添加到场景that.filterEmptyMeshes()
that.scene.add(object);
console.log("Model added to scene");
});
});
this.animate();
window.addEventListener("resize", () => {
this.onWindowResize();
});
}
2、obj 数据,其中mtl文件一定要是相对路径(且mtl 不要带中文),不然在apk 调试也请求不到。
带中文报错截图,忘记截图了,在apk运行到手机模拟器一看就知道了。
3、最后,利用vue 打包好的拷贝到hbuilderX发布apk,示例参考很多,利用5+app发布就可以了(发布前可以自己运行调试下),如图红框即为替换的内容。npm run build 打包出来的内容
利用5+app模版,将相应内容更换后的布局。
注意点是index.html 中的路径要修改,具体,全局搜索/css和/js的将其修改为css和js。修改前
修改后
成果展示: