threejs加载stl模型在uniapp中的应用(打包安卓)

threejs加载stl模型在uniapp中的应用(打包安卓), 在template模版中直接读取renderjs的值比如 threeArea.modelFileLink 在安卓打包后会报错,但是在H5页面中可以正常读取,最后是通过ownerVm.callMethod('receiveRenderData', true); 传递给逻辑层解决的
在安卓系统中threejs通过renderjs才能显示在页面上,否则无法显示,但是在H5页面中可以不用renderjs,能正常读取

xml 复制代码
<template>
  <view>
    <template v-show="progressLoading">
      <view id="container"></view>
      <view id="threeArea" :option="option" :change:option="threeArea.receiveInfo"></view>

      <!-- <view style="position: absolute; top:0; left: 0; right: 0; height: 200rpx; background: #ff0;">
        <image :src='imgLink' mode="heightFix" v-if="imgLink" style="width: 200rpx;"></image>
        <view>{{ imgLink}}</view>
      </view> -->
      <view class="detail_btn" style="text-align: center;">
        <u-button type="primary" class="detail_btns" @click="capture">截图并对比</u-button>
      </view>
    </template>
    <template v-if="!progressLoading">
      <view style="position: fixed; top: 0; bottom: 0; left: 0; right: 0; display: flex; justify-content: center; align-items: center; background: rgba(0,0,0, .8); color: #fff">模型正在加载中 {{ progressNumber }}</view>
    </template>
    <u-modal title="" :show="popupShow" :showCancelButton="true" cancelText="返回" confirmText="去对比"
      @cancel="popupShow=false" @confirm="gotoCamera">
      <view class="popup_cont">
        <image :src='imgLink' mode="heightFix"></image>
      </view>
    </u-modal>
  </view>
</template>
<script>
  import {
    uploadFile
  } from '@/api/upload.js'
  export default {
    data() {
      return {
        option: {
          modelFile: null,
          storedLines: null
        },
        popupShow: false,
        imgLink: null,
        progressLoading: false,
        progressNumber: '0%',
      };
    },
    mounted() {
      const storedLines = uni.getStorageSync('lines');
      this.option.storedLines = storedLines || []
    },
    onLoad(options) {
      this.option.modelFile = this.$imgUrl + options.modelFile
      console.log('this.option.modelFile :', this.option.modelFile );
      uni.setNavigationBarTitle({
        title: options.modelTitle
      })
    },
    methods: {
      capture() {
        // this.popupShow = true;
        this.getImage('album');
      },
      gotoCamera() {
        uni.navigateTo({
          url: '/pages/camera/camera?img=' + this.imgLink
        })
      },

      getImage(type) {
        uni.chooseImage({
          sourceType: [type],
          crop: {
            quality: 80,
            width: 300,
            height: 350
          }, // 图片上传前做裁剪
          // sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
          success: (res) => {
            for (let i = 0; i < res.tempFilePaths.length; i++) {
              uni.getImageInfo({
                src: res.tempFilePaths[i],
                success: async (image) => {
                  const res2 = await uploadFile(res.tempFilePaths[i])
                  this.imgLink = this.$imgUrl + res2.data.newFile
                  uni.redirectTo({
                    url: '/pages/camera/camera?img=' + this.imgLink
                  })
                }
              });
            }
          }
        });
      },
      receiveRenderData(val){
        this.progressLoading = val
      },
      // 接受rendjs的值
      renderProgressNumber(val) {
        this.progressNumber = val 
      }

    },
  };
</script>

<script module="threeArea" lang="renderjs">
  import * as THREE from 'three'
  import {
    OrbitControls
  } from 'three/examples/jsm/controls/OrbitControls.js'
  // 引入stl加载器
  import {
    STLLoader
  } from 'three/examples/jsm/loaders/STLLoader.js'

  var renderer, scene, camera, controls;

  export default {
    data() {
      return {
        modelFileLink: null,
        ownerVm: null,
      };
    },
    mounted() {},
    methods: {
      receiveInfo(newValue, oldValue, ownerVm, vm) {
        if (newValue) {
          this.initThree(newValue.modelFile);
          // this.createGridHelper();
          this.createControls();
          // this.loadLinesFromStorage(newValue.storedLines);
          console.log('this.ownerVm222222:' ,ownerVm);
          this.ownerVm = ownerVm
        }
      },
      
      initThree(modelFile) {
        this.progressLoading = false
        let container = document.getElementById('container')
        scene = new THREE.Scene()
        scene.background = new THREE.Color(0xECECEE);
        const loader = new STLLoader()
         console.log('before.loading');
        // 把模型导入STLLoader加载器中 
        // loader.load('http://192.168.10.121:5500/a.stl', geometry => {
        loader.load(modelFile, geometry => {
          console.log('loading');
          //创建一个BufferGeometry函数
          const geometry1 = new THREE.BufferGeometry();
          // geometry.attributes.position.array这个是获取模型的坐标  第二个参数: 3是三个数为一个坐标就是一个顶点
          geometry1.setAttribute('position', new THREE.BufferAttribute(geometry.attributes
            .position.array, 3))
          const material1 = new THREE.MeshLambertMaterial({
            color: 0xDACFBC, //0x00ff00 0xff0000设置材质颜色为红色
            transparent: true, //开启透明
            opacity: 0.96, //设置透明度
          });
          geometry.center();
          const mesh = new THREE.Mesh(geometry, material1);
          mesh.position.set(0, 12, 0)
          mesh.scale.set(.8, .8, .8)
          // mesh.position.set.x = 5 * Math.PI; //模型摆正   用这个就不用上面的position
          mesh.castShadow = true;
          scene.add(mesh);
        },
        (progress) => {
          let progressNumber = `${Math.trunc(progress.loaded / progress.total * 100)}%`
          setTimeout(()=> {
            // 给逻辑层传递值
            this.ownerVm.callMethod('renderProgressNumber', progressNumber);
          }, 100);
          
          if(progress.loaded === progress.total) {
            // 加载完成
            setTimeout(()=> {
              this.ownerVm.callMethod('receiveRenderData', true);
            }, 100);
          }
        },
        (err) => {
          console.error('加载失败:', err);
        });
        camera = new THREE.PerspectiveCamera(65, container.clientWidth / container.clientHeight, 0.1, 100)
        // this.camera.position.z = 0.3
        camera.position.set(-50, 0, 50)
        // 设置照相机的朝向
        camera.lookAt(-50, -50, -50)
        // const directionalLight = new Three.DirectionalLight(0xFFFFFF,3.0);
        // directionalLight.position.set(80, 100, 50);
        // this.scene.add(directionalLight);
        var hemiLight = new THREE.HemisphereLight(0xDACFBC, 1) //0xFFFFFF
        hemiLight.position.set(100, 100, 100)
        scene.add(hemiLight)

        renderer = new THREE.WebGLRenderer({
          antialias: true
        })
        renderer.setSize(container.clientWidth, container.clientHeight)
        container.appendChild(renderer.domElement)

        this.render();
      },
      createGridHelper() {
        // 设置网格
        const gridHelper = new THREE.GridHelper(50, 10);
        scene.add(gridHelper);
      },
      createControls() {
        controls = new OrbitControls(camera, renderer.domElement);
      },
      render() {
        requestAnimationFrame(() => this.render());
        renderer.render(scene, camera);
      },
      destroyThreeJSInstance() {
        // 移除事件监听器
        // object.removeEventListener('click', onClick);

        // 清除渲染器和画布
        renderer.dispose();
        document.getElementById('container').removeChild(renderer.domElement);

        // 删除场景中的所有对象
        scene.traverse((object) => {
          if (object.isMesh) {
            object.geometry.dispose();
            object.material.dispose();
          }
        });

        // 重置相机和其他辅助对象
        camera.position.set(0, 0, 0);

        // 解除引用
        scene = null;
        camera = null;
        renderer = null;
      },
    }
  };
</script>

<style scoped lang="scss">
  #container {
    height: 100vh;
  }

  .detail_btn {
    position: fixed;
    bottom: 30rpx;
    left: 30rpx;
    right: 30rpx;

    .detail_btns {
      width: 630rpx;
      height: 100rpx;
      line-height: 100rpx;
      font-size: 32rpx;
      border-radius: 60rpx;
      background: #437DFF;
    }
  }

  .popup_cont {
    width: 653rpx;
    height: 60vh;
    border-radius: 8rpx;
    display: flex;
    justify-content: center;
    align-items: center;
  }
</style>
相关推荐
优雅永不过时·4 天前
实现一个漂亮的Three.js 扫光地面 圆形贴图扫光
前端·javascript·智慧城市·three.js·贴图·shader
3D虚拟工厂10 天前
1️⃣7️⃣three.js_OrbitControls相机控制器
javascript·3d·vue·blender·three.js·uv
3D虚拟工厂11 天前
OrbitControls
three.js
VcB之殇14 天前
three.js中使用canvas生成动态纹理贴图
javascript·three.js
Mintopia14 天前
Three.js 在数字孪生中的应用场景教学
前端·javascript·three.js
FanetheDivine14 天前
three.js学习笔记 2.光照和材质
react.js·three.js
雨夜带刀_15 天前
vue+three.js贴图-自定义贴图.仿写VANS定制功能(three.js+vue)
three.js
小桥风满袖15 天前
Three.js-硬要自学系列19 (曲线颜色渐变、渐变插值、查看设置gltf顶点、山脉高度可视化)
前端·css·three.js
Mintopia15 天前
# 使用 Three.js 实现带随机障碍物的小车行驶模拟
前端·javascript·three.js
渣渣宇a16 天前
Three_3D_Map 中国多个省份的组合边界绘制,填充背景
前端·javascript·three.js