一、前期调研

因小程序环境下,没有浏览器相关的运行环境如window, document等,所以在小程序中使用three.js需要使用相应的移植版本。
调研了以下三种:
①微信官方给出的版本:
https://github.com/wechat-min...
加载不带贴图的glb文件没问题。但加载带贴图的glb文件报错,对loader文件没有做移植,并且看官方不怎么维护了。
②three平台化产品,但是感觉上手不是特别友好,并且比较大。
https://github.com/deepkolos/...
③yannliao微信官方社区里比较热门的版本
https://github.com/yannliao/t...

最终使用了第三种,对glb带材质的文件也能正常加载。

二、使用教程

1、在示例仓库(https://github.com/yannliao/t...)中,下载 libs及jsm文件夹,放入自己项目根目录下
2、在index.js页面的js文件下引入three

import * as THREE from '../../libs/three.weapp.min.js'
import { OrbitControls } from '../../jsm/loaders/OrbitControls'

Page({
  data: {},
  onLoad: function () {
    wx.createSelectorQuery()
      .select('#c')
      .node()
      .exec((res) => {
        const canvas = THREE.global.registerCanvas(res[0].node)

        this.setData({ canvasId: canvas._canvasId })

        const camera = new THREE.PerspectiveCamera(70, canvas.width / canvas.height, 1, 1000);
        camera.position.z = 500;
        const scene = new THREE.Scene();
        scene.background = new THREE.Color(0xAAAAAA);
        const renderer = new THREE.WebGLRenderer({ antialias: true });

        const controls = new OrbitControls(camera, renderer.domElement);
        // controls.enableDamping = true;
        // controls.dampingFactor = 0.25;
        // controls.enableZoom = false;
        camera.position.set(200, 200, 500);
        controls.update();
        const geometry = new THREE.BoxBufferGeometry(200, 200, 200);

        const texture = new THREE.TextureLoader().load('./pikachu.png');
        const material = new THREE.MeshBasicMaterial({ map: texture });

        // const material = new THREE.MeshBasicMaterial({ color: 0x44aa88 });
        const mesh = new THREE.Mesh(geometry, material);
        scene.add(mesh);

        // renderer.setPixelRatio(wx.getSystemInfoSync().pixelRatio);
        // renderer.setSize(canvas.width, canvas.height);

        function onWindowResize() {
          camera.aspect = window.innerWidth / window.innerHeight;
          camera.updateProjectionMatrix();
          renderer.setSize(canvas.width, canvas.height);
        }
        function render() {
          canvas.requestAnimationFrame(render);
          // mesh.rotation.x += 0.005;
          // mesh.rotation.y += 0.01;
          controls.update();
          renderer.render(scene, camera);
        }

        render()

      })
  },
  onUnload: function () {
    THREE.global.unregisterCanvas(this.data.canvasId)
  },
  touchStart(e) {
    console.log('canvas', e)
    THREE.global.touchEventHandlerFactory('canvas', 'touchstart')(e)
  },
  touchMove(e) {
    console.log('canvas', e)
    THREE.global.touchEventHandlerFactory('canvas', 'touchmove')(e)
  },
  touchEnd(e) {
    console.log('canvas', e)
    THREE.global.touchEventHandlerFactory('canvas', 'touchend')(e)
  },
  touchCancel(e) {
    // console.log('canvas', e)
  },
  longTap(e) {
    // console.log('canvas', e)
  },
  tap(e) {
    // console.log('canvas', e)
  },
  documentTouchStart(e) {
    // console.log('document',e)
  },
  documentTouchMove(e) {
    // console.log('document',e)
  },
  documentTouchEnd(e) {
    // console.log('document',e)
  },
})

3、 在index.wxml中加入canvas组件, 其中需要手动绑定相应的事件,用于手势控制。

<view style="height: 100%; width: 100%;" bindtouchstart="documentTouchStart" bindtouchmove="documentTouchMove" bindtouchend="documentTouchEnd" >
    <canvas type="webgl" id="c" style="width: 100%; height:100%;" bindtouchstart="touchStart" bindtouchmove="touchMove" bindtouchend="touchEnd" bindtouchcancel="touchCancel" bindlongtap="longTap" bindtap="tap"></canvas>
</view>

三、踩坑记录

Q1:为何示例里面的模型,在真机预览上都看不到?

答:原因在于模型下载地址,不在小程序request合法域名中。如果只是想真机浏览下效果,不考虑日后上线问题,可以在真机预览轻快下,打击页面右边上面的3个点,选择打开调试即可,这相当于开发工具勾选不效验合法域名。或是日后要上线,那就把模型放到你自己的服务器上,要有域名的,icp备过案的,https的服务器。这是微信的要求,不是threejs的要求。

Q2:模型能看到了,但是贴图看不到?

答:如果引用都正确的情况下看不到,那就是,贴图尺寸的问题,threejs有限制图片尺寸,目前测试最大为2048。并且图片的大小要为2的冥数倍。

Q3:我不想只在调试模式下能看到模型,但是域名服务器那些,我也搞不明白,有没有办法,让我在正常体验版下也可以给别人浏览我的模型?

答:之前我也被这个问题困扰过,微信小程序如果是云开发版时,会有一个免费的5G的云数据库和存储空间,我们的突破就是它。存进去后,我们常用的是fileID,但是这里,我要使用的是它的下载地址,https开头的哟,并且可以成功添加进合法域名,问题解决。那非云开发版本怎么办呢,unicloud也提供免费的云存储,你创建一个云空间后,云存储上传即可,点击详情可以看到https的路径。

03-05 15:35