threeJS 模型中加载html页面

目录

0. 效果图

1. CSS3DRenderer介绍

2. CSS3DObject介绍

3. 完整代码

0. 效果图

最近遇到一个新的需求,在threeJS的模型中加载我们的普通的H5页面,研究了下,发现threeJS中自带的CSS3DRenderer可以实现,先放一张展示图

 可以看到,中间的面板就是加载的threeJS官网页面,并且可以操作互动

1. CSS3DRenderer介绍

CSS3DRenderer通过CSS3的transforms属性,将层级的3D变换应用到Dom元素上,将Dom元素和WebGL的内容相结合,操作Dom元素的positionh和rotation属性来创建动画。

代码结构:

 /**
       * CSS3DRenderer通过CSS3的transforms属性,将层级的3D变换应用到Dom元素上,将Dom元素和WebGL的内容相结合,Dom => Object3D
       * 操作Dom元素的positionh和rotation属性来创建动画
       * @type {CSS3DRenderer}
       */
      this.labelRenderer = new CSS3DRenderer();
      this.labelRenderer.setSize(this.container.clientWidth, this.container.clientHeight);
      this.labelRenderer.domElement.style.position = "absolute";
      this.labelRenderer.domElement.style.top = 0;
      this.container.appendChild(this.labelRenderer.domElement);
      console.log(this.labelRenderer);
      //创建控件对象
      this.controls = new OrbitControls(this.camera, this.labelRenderer.domElement);

同时创建控件对象,把CSS3DRenderer的场景加入控制器中

CSS3DRenderer跟场景下的Render一样,需要进行render()场景渲染处理

this.labelRenderer.render(this.scene, this.camera);

2. CSS3DObject介绍

配合CSS3DRenderer,将创建的Dom元素通过CSS3DObject包装成3D对象

DOM => Object3D

代码结构:

let domEle = document.createElement("div");
      domEle.innerHTML = "<div class='domBox'><iframe src='https://threejs.org/docs/index.html#manual/en/introduction/Creating-a-scene'></iframe></div>"
      /**
       * 将创建的Dom元素用过CSS3DObject包装成3D对象
       * @type {CSS3DObject}
       */
      let domEleObj = new CSS3DObject(domEle);
      domEleObj.position.set(-150, -50, -380);
      this.scene.add(domEleObj);

将把转换后的3D对象直接加入场景中即可

3. 完整代码

<template>
  <div class="wrap">
    <div ref="container" id="container"></div>
  </div>
</template>
<script>
import * as THREE from "three";
import {OrbitControls} from "three/examples/jsm/controls/OrbitControls.js";
import {CSS3DRenderer, CSS3DObject} from "three/examples/jsm/renderers/CSS3DRenderer.js";

export default {
  name: "ThreeTest",
  mounted() {
    this.myReq = null
    this.container
    this.scene
    this.camera
    this.renderer
    this.labelRenderer
    this.controls
    this.initRender();
    this.initScene();
    this.initModel();
    this.animate();
    window.onresize = this.onWindowResize;
  },
  methods: {
    getTexturesFromAtlasFile(atlasImgUrl, tilesNum) {
      const textures = [];
      for (let i = 0; i < tilesNum; i++) {
        textures[i] = new THREE.Texture();
      }
      new THREE.ImageLoader().load(atlasImgUrl, (image) => {
        let canvas, context;
        const tileWidth = image.height;
        for (let i = 0; i < textures.length; i++) {
          canvas = document.createElement('canvas');
          context = canvas.getContext('2d');
          canvas.height = tileWidth;
          canvas.width = tileWidth;
          context.drawImage(image, tileWidth * i, 0, tileWidth, tileWidth, 0, 0, tileWidth, tileWidth);
          textures[i].image = canvas;
          textures[i].needsUpdate = true;
        }
      });
      return textures;
    },
    initRender: function () {
      this.container = document.getElementById("container");
      this.camera = new THREE.PerspectiveCamera(
        70,
        this.container.clientWidth / this.container.clientHeight,
        1,
        1000
      );
      this.camera.position.z = 1;
      this.renderer = new THREE.WebGLRenderer({antialias: true});
      this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);
      this.container.appendChild(this.renderer.domElement);
      /**
       * CSS3DRenderer通过CSS3的transforms属性,将层级的3D变换应用到Dom元素上,将Dom元素和WebGL的内容相结合,Dom => Object3D
       * 操作Dom元素的positionh和rotation属性来创建动画
       * @type {CSS3DRenderer}
       */
      this.labelRenderer = new CSS3DRenderer();
      this.labelRenderer.setSize(this.container.clientWidth, this.container.clientHeight);
      this.labelRenderer.domElement.style.position = "absolute";
      this.labelRenderer.domElement.style.top = 0;
      this.container.appendChild(this.labelRenderer.domElement);
      console.log(this.labelRenderer);
      //创建控件对象
      this.controls = new OrbitControls(this.camera, this.labelRenderer.domElement);
    },
    initScene() {
      this.scene = new THREE.Scene();
    },
    initModel() {
      const textures = this.getTexturesFromAtlasFile('source/sun_temple_stripe.jpg', 6);
      const materialArr = [];
      for (let i = 0; i < 6; i++) {
        materialArr.push(new THREE.MeshBasicMaterial({map: textures[i]}));
      }
      var boxGeometry = new THREE.BoxGeometry(200, 200, 200, 100, 100, 100);
      boxGeometry.scale(1, 1, -1);
      let cube = new THREE.Mesh(boxGeometry, materialArr);
      this.scene.add(cube);
      let domEle = document.createElement("div");
      domEle.innerHTML = "<div class='domBox'><iframe src='https://threejs.org/docs/index.html#manual/en/introduction/Creating-a-scene'></iframe></div>"
      /**
       * 将创建的Dom元素用过CSS3DObject包装成3D对象
       * @type {CSS3DObject}
       */
      let domEleObj = new CSS3DObject(domEle);
      domEleObj.position.set(-150, -50, -380);
      this.scene.add(domEleObj);
    },
    render() {
      this.renderer.render(this.scene, this.camera);
      this.labelRenderer.render(this.scene, this.camera);
    },
    onWindowResize() {
      this.camera.aspect = window.innerWidth / window.innerHeight;
      this.camera.updateProjectionMatrix();
      this.render();
      this.renderer.setSize(window.innerWidth, window.innerHeight);
    },
    animate() {
      this.render();
      this.myReq = requestAnimationFrame(this.animate);
    }
  },
  beforeDestroy() {
    cancelAnimationFrame(this.myReq)
    this.scene = null
    this.scene.dispose()
    this.camera = null
    this.renderer = null
    this.labelRenderer = null
    this.controls = null
  }
};
</script>
<style>
.wrap {
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 100;
}

#container {
  height: 100%;
}

.domBox {
  width: auto;
}

</style>

猜你喜欢

转载自blog.csdn.net/jinse29/article/details/129995225