序文:
我的需求是使用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>
上記の場合、2 つのモデルが使用されます。1 つの obj モデル、obj モデルのアドレスは、自分で作成する必要があるローカル サーバーのアドレスであり、GLTF モデルのアドレスはネットワーク アドレスです。 、注釈のロックを解除することで表示できます。
注意点:
1. 外部モデルの読み込みはthreeJs公式サイトのAPIと一致しています
2. この方法で外部モデルを読み込むと、実機デバッグ中にモデルが表示されなかったり、WeChatがクラッシュしたりする事態が発生する場合があります(理由は不明です)
Webview の実装で threejs ライブラリを導入
効果図
実現:
1. vue を使用して threejs を実装して obj モデルをインポートします (pc エンドは完全に実現できます)
2. 対応するモデルの表示アドレスを webview に導入します,
終了、この2つのステップだけで十分ですが、モデルを動的にロードしているため、モデルをロードするときに、アプレット側からPC側に値を渡す必要があるため、PC側が対応するモデルをロードします。アドレスで get を使用するだけで済みます。列にパラメーターを渡すだけです。
次の 2 つの方法を使用できます。
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 = camera.position.z / maxDiameter;
obj.position.set(0, -10, 0);//模型摆放的位置
obj.scale.set(scaleValue, scaleValue, scaleValue);
scene.add(obj);
},
2. Web ビューを表示するときにアプレットがプルダウンするのを禁止します
。mounted
document.body.addEventListener('touchmove', function (e) {
e.preventDefault();
}, {
passive: false });