這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助

前言
我的需求是使用uniapp寫微信小程式,在小程式中使用threeJs就行了,目前暫不考慮兼容app什么的, 1.引入小程式版的threejs庫實作 2.使用webview實作(推薦)
重點
我的建議是使用這個庫
https://github.com/deepkolos/three-platformize
為什么?我試了uniapp推薦的和threejs-miniprogram這個小程式官方庫,都加載不出來我的obj模型,所有我推薦不要用obj模型最好,挺多都支持GLTF模型的,但是我不能改,
使用three-platformize加載obj模型的案例:

核心代碼:
html:
<canvas type="webgl" id="webgl" style="width: 100vw; height: 100vh;"
@touchstart="touchStart"
@touchmove="touchMove"
@touchend="touchEnd"
/>
script:
<script>
import * as THREE from 'three-platformize';
import { WechatPlatform } from 'three-platformize/src/WechatPlatform';
import { OBJLoader } from 'three-platformize/examples/jsm/loaders/OBJLoader';
import { GLTFLoader } from 'three-platformize/examples/jsm/loaders/GLTFLoader';
import {OrbitControls} from 'three-platformize/examples/jsm/controls/OrbitControls';
export default {
data() {
return {
canvas:null,
camera:null,
scene:null,
renderer:null,
model:null,
controls:null,
loopIndex:null
}
},
onLoad() {
},
methods: {
async init() {
const { canvas }= await this.getCanvas();
this.canvas = canvas;
const platform = new WechatPlatform(canvas); // webgl canvas
platform.enableDeviceOrientation('game'); // 開啟DeviceOrientation
THREE.PLATFORM.set(platform);
this.platform = platform;
this.renderModel();
},
//獲取畫布
async getCanvas(delay = 200) {
return new Promise((resolve, reject) => {
const t = setTimeout(() => {
clearTimeout(t);
uni.createSelectorQuery().in(this)
.select('#webgl')
.fields({ node: true })
.exec((res) => {
console.log('res',res)
if (res && res[0] && res[0].node) {
const canvas = res[0].node;
resolve({ canvas });
} else {
reject("獲取canvas失敗");
}
});
}, delay);
});
},
renderModel () {
this.camera = new THREE.PerspectiveCamera(45, this.canvas.width / this.canvas.height, 0.25, 100);
this.camera.position.set(- 5, 3, 10);
this.camera.lookAt(new THREE.Vector3(0, 2, 0));
this.scene = new THREE.Scene();
this.scene.background = new THREE.Color(0xe0e0e0);
this.scene.fog = new THREE.Fog(0xe0e0e0, 20, 100);
this.clock = new THREE.Clock();
// lights
var light = new THREE.HemisphereLight(0xffffff, 0x444444);
light.position.set(0, 20, 0);
this.scene.add(light);
// 改變外殼顏色
var AmbientLight = new THREE.AmbientLight(0x815800); // 環境光
this.scene.add(AmbientLight);
// 平行光
light = new THREE.DirectionalLight(0xffffff);
light.position.set(0, 20, 10);
this.scene.add(light);
// // ground
// var mesh = new THREE.Mesh(new THREE.PlaneBufferGeometry(2000, 2000), new THREE.MeshPhongMaterial({ color: 0x999999, depthWrite: false }));
// mesh.rotation.x = - Math.PI / 2;
// this.scene.add(mesh);
// var grid = new THREE.GridHelper(200, 40, 0x000000, 0x000000);
// grid.material.opacity = 0.6;
// grid.material.transparent = true;
// this.scene.add(grid);
// model
var loader = new OBJLoader();
loader.load('http://localhost:8888/obj3/file.obj', (obj) => {
console.log("obj+=")
console.log(obj)
// console.log(this.model)
obj.position.set(0, -2, 0);//模型擺放的位置
obj.scale.set(0.2, 0.2, 0.2);
// this.model = obj;
this.scene.add(obj);
}, undefined, function (e) {
console.log("模型加載錯誤")
console.error(e);
});
// var loader = new GLTFLoader();
// loader.load('https://dtmall-tel.alicdn.com/edgeComputingConfig/upload_models/1591673169101/RobotExpressive.glb', (gltf) => {
// this.model = gltf.scene;
// this.scene.add(this.model);
// }, undefined, function (e) {
// console.error(e);
// });
// var geometry = new THREE.BoxGeometry( 5, 5, 5 );
// var material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
// var mesh = new THREE.Mesh( geometry, material );
// this.scene.add(mesh);
this.renderer = new THREE.WebGLRenderer({antialias: true });
this.renderer.setPixelRatio(wx.getSystemInfoSync().pixelRatio);
this.renderer.setSize(this.canvas.width, this.canvas.height);
//this.renderer.outputEncoding = true;
this.renderer.gammaFactor = 2.2;
this.controls = new OrbitControls(this.camera, this.renderer.domElement );
this.camera.position.set( 5, 5, 10 );
this.animate();
},
animate() {
this.loopIndex = this.canvas.requestAnimationFrame(this.animate);
this.renderer.render(this.scene, this.camera);
this.controls.update();
},
touchStart(e) {
this.platform.dispatchTouchEvent(e);
},
touchMove(e) {
this.platform.dispatchTouchEvent(e);
},
touchEnd(e) {
this.platform.dispatchTouchEvent(e);
}
},
mounted() {
this.$nextTick(()=> {
this.init();
});
}
}
</script>
上面的案例中使用了兩個模型,一個obj模型,obj模型的地址是自己寫的本地服務器地址,需要自己配置,GLTF模型地址是網路地址,可以把注釋解開查看,
注意點
1.加載外部模型與threeJs官網api是一致的
2.使用此方法加載外部模型,可能在真機除錯時遇到模型不展示,或者微信閃退的情況(原因未知)
webview實作引入threejs庫
效果圖

實作:
1.使用vue實作threejs匯入obj模型(pc端可完美實作),
2.在webview中引入相應的模型展示地址,
完結,就這兩步即可,但是我是動態加載,所以在加載模型的時候,你需要在小程式端傳值給pc端,讓pc端加載相應的模型,這里就只需要用get在地址欄中傳參就行了,
以下兩個方法可能會用到:
1.模型大小自適應
setScaleToFitSize (obj) {
const boxHelper = new THREE.BoxHelper(obj);
boxHelper.geometry.computeBoundingBox();
const box = boxHelper.geometry.boundingBox;
const maxDiameter = Math.max((box.max.x - box.min.x), (box.max.y - box.min.y), (box.max.z - box.min.z));
const scaleValue = https://www.cnblogs.com/smileZAZ/archive/2022/11/28/camera.position.z / maxDiameter;
obj.position.set(0, -10, 0);//模型擺放的位置
obj.scale.set(scaleValue, scaleValue, scaleValue);
scene.add(obj);
},
2.禁止小程式展示webview時候向下拉動:
在mounted中添加:
document.body.addEventListener('touchmove', function (e) {
e.preventDefault();
}, { passive: false });
本文轉載于:
https://blog.csdn.net/hzqzzz/article/details/126428029
如果對您有所幫助,歡迎您點個關注,我會定時更新技術檔案,大家一起討論學習,一起進步,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/538662.html
標籤:其他
