thee.js完成线上展厅demo

思路 ,创建盒子 ,前进按钮, 第一次进去创建一个盒子 盒子上添加图片纹理

也就是天空盒子一样的

在创建 一个面 设置好对应的角度和位置

csharp 复制代码
// 创建 前进的标签
function createLandMark(obj) {
  const { imgUrl, wh, position, rotation, targetAttr } = obj;
  const geometry = new THREE.PlaneGeometry(...wh);
  const material = new THREE.MeshBasicMaterial({ map: (new THREE.TextureLoader().load(imgUrl)), side: THREE.DoubleSide,transparent: true,});
  const mesh = new THREE.Mesh(geometry,material)
  mesh.position.set(...position);
  mesh.rotation.set(...rotation);
  mesh.name = 'landmark'
  mesh.userData.attr = targetAttr;
  group.add(mesh)
  // addGUI(mesh)
  
} 
csharp 复制代码
// 创建盒子  设置盒子里面贴图的内容  
function  createcube() {
  const geometry = new THREE.BoxGeometry(1, 1, 1);
  const material = new THREE.MeshBasicMaterial({ color: 0x00ff00,side: THREE.DoubleSide });
  const cube = new THREE.Mesh(geometry, material);
  cube.scale.set(1, 1, -1); // 图片防止倒置
  scene.add(cube);
  return cube;
}

// 个面具数据更新盒子的背景
function setMaterialCube(infoObj){
  clear();
const {publicPath,imgUrlArr,markList} = infoObj;
const textureLoader = new THREE.TextureLoader();
textureLoader.setPath(publicPath);
const materialArr = imgUrlArr.map((item) => {
  const texture = textureLoader.load(item);
  texture.colorSpace = THREE.SRGBColorSpace;

  return new THREE.MeshBasicMaterial({ map: texture,side: THREE.DoubleSide });
});
  console.log(materialArr,'materialArr');
  console.log(cubeObj,'cubeObj');
  cubeObj.material = materialArr;
  markList.forEach((item) => {
    if (item.name === 'landmark') {
      createLandMark(item);
    } else if (item.name === 'dom') {
      createDom(item);
    } else if (item.name === 'tvdom') {
      createtvDom(item);
    }

  });
  scene.add(group)
}
// 每次需要清空上次的背景  所以添加到goup组中方便操作
function clear() {
  const list = [...group.children]
  list.forEach((item) => {
    if (!item.isCSS3DObject) {
      item.geometry.dispose();
      item.material.dispose();
    }
    group.remove(item)

  })
}

创建按钮的绑定事件

csharp 复制代码
// 绑定点击事件
function bindClickEvent() {
  const rayCaster = new THREE.Raycaster()
  const pointer = new THREE.Vector2()
  window.addEventListener('click', (e) => {
    pointer.x = ( e.clientX / window.innerWidth ) * 2 - 1;
    pointer.y = - ( e.clientY / window.innerHeight ) * 2 + 1;

    rayCaster.setFromCamera( pointer, camera );
    const list = rayCaster.intersectObjects( scene.children );
    const item1 = list.find(item=>item.object.name === 'landmark')
    if (item1) {
      let targetObj = sceneInfoObj[item1.object.userData.attr];
      console.log(targetObj,'targetObj');
      setMaterialCube(targetObj);
    }
  })
}

完整代码

csharp 复制代码
import {scene, camera, renderer, controls} from './utils/init.js';
import addGUI from './utils/gui.js';
import * as THREE from 'three';
// 引入CSS3模型对象CSS3DObject
import { CSS3DObject } from 'three/addons/renderers/CSS3DRenderer.js';
// 设置相机距离限制,确保鼠标滚动不能超过1
controls.minDistance = -0.5; // 最小距离
controls.maxDistance = 0.5; // 最大距离,不能超过1
const group = new THREE.Group()
const sceneInfoObj = {
  one:{
    publicPath: 'tecimg/1/',
    imgUrlArr: [
      'px.png',
      'nx.png',
      'py.png',
      'ny.png',
      'pz.png',
      'nz.png',
    ],
    markList: [
      {
        name: 'landmark',
        imgUrl:'other/landmark.png',
        wh:[0.05,0.05],
        position: [-0.07,-0.05,-0.48],
        rotation: [1.76,0,0],
        targetAttr:'two'
      }
    ]
  },
  two:{
    publicPath: 'tecimg/2/',
    imgUrlArr: [
      'px.png',
      'nx.png',
      'py.png',
      'ny.png',
      'pz.png',
      'nz.png',
    ],
    markList: [
      {
        name: 'landmark',
        imgUrl:'other/landmark.png',
        wh:[0.05,0.05],
        position: [0.47,-0.14,0.3],
        rotation: [1.55,0.06,0],
        targetAttr:'one'
      },
      {
        name: 'landmark',
        imgUrl:'other/landmark.png',
        wh:[0.05,0.05],
        position: [-0.48,-0.03,0.01],
        rotation: [1.49,0.46,1.08],
        targetAttr:'three'
      }
    ]
  }, 
  three:{
    publicPath: 'tecimg/3/',
    imgUrlArr: [
      'px.png',
      'nx.png',
      'py.png',
      'ny.png',
      'pz.png',
      'nz.png',
    ],
    markList: [
      {
        name: 'landmark',
        imgUrl:'other/landmark.png',
        wh:[0.05,0.05],
        position: [-0.12,-0.01,0.3],
        rotation: [1.35,3.12,0],
        targetAttr:'two'
      },
      {
        name: 'dom',
        position: [0.25,0.01,-0.66],
        rotation: [0,0,0],
        scale:[1/800,1/800,1/800],
        targetAttr:'four',
        innerHTML:'前进',
        active:(e) => {
          // alert('点击了dom')
          setMaterialCube(sceneInfoObj.four)
          // console.log(e,'e');
        }

      }
    ]
  },
  four:{
    publicPath: 'tecimg/4/',
    imgUrlArr: [
      'px.png',
      'nx.png',
      'py.png',
      'ny.png',
      'pz.png',
      'nz.png',
    ],
    markList: [
      {
        name: 'landmark',
        imgUrl:'other/landmark.png',
        wh:[0.05,0.05],
        position: [-0.4,-0.03,0.01],
        rotation: [1.55,2.98,0],
        targetAttr:'three'
      },
      {
        name: 'tvdom',
        position: [-0.09,0.34,-0.21],
        rotation: [0.87,0,0],
        scale:[1/500,1/500,1/600],
        tv:(e) => {
          console.log(e,'e');
        }

      }
    ]
  }
}

function  createcube() {
  const geometry = new THREE.BoxGeometry(1, 1, 1);
  const material = new THREE.MeshBasicMaterial({ color: 0x00ff00,side: THREE.DoubleSide });
  const cube = new THREE.Mesh(geometry, material);
  cube.scale.set(1, 1, -1);
  scene.add(cube);
  return cube;
}


function setMaterialCube(infoObj){
  clear();
const {publicPath,imgUrlArr,markList} = infoObj;
const textureLoader = new THREE.TextureLoader();
textureLoader.setPath(publicPath);
const materialArr = imgUrlArr.map((item) => {
  const texture = textureLoader.load(item);
  texture.colorSpace = THREE.SRGBColorSpace;

  return new THREE.MeshBasicMaterial({ map: texture,side: THREE.DoubleSide });
});
  console.log(materialArr,'materialArr');
  console.log(cubeObj,'cubeObj');
  cubeObj.material = materialArr;
  markList.forEach((item) => {
    if (item.name === 'landmark') {
      createLandMark(item);
    } else if (item.name === 'dom') {
      createDom(item);
    } else if (item.name === 'tvdom') {
      createtvDom(item);
    }

  });
  scene.add(group)
}

function clear() {
  const list = [...group.children]
  list.forEach((item) => {
    if (!item.isCSS3DObject) {
      item.geometry.dispose();
      item.material.dispose();
    }
    group.remove(item)

  })
}
function createLandMark(obj) {
  const { imgUrl, wh, position, rotation, targetAttr } = obj;
  const geometry = new THREE.PlaneGeometry(...wh);
  const material = new THREE.MeshBasicMaterial({ map: (new THREE.TextureLoader().load(imgUrl)), side: THREE.DoubleSide,transparent: true,});
  const mesh = new THREE.Mesh(geometry,material)
  mesh.position.set(...position);
  mesh.rotation.set(...rotation);
  mesh.name = 'landmark'
  mesh.userData.attr = targetAttr;
  group.add(mesh)
  // addGUI(mesh)
  
} 

function createDom(obj) {
  console.log(obj,'obj111');
  const { position, rotation, targetAttr,active,innerHTML,scale } = obj;
  const div = document.createElement('div');
  div.style.position = 'fixed';
  div.style.left = `0%`;
  div.style.top = `0%`;
  div.style.padding = `10px`;
  div.style.backgroundColor = 'red';
  div.innerHTML = innerHTML
  div.addEventListener('click',e=>{
    active(e)
  })
  const tag = new CSS3DObject(div);
  tag.scale.set(...scale)
  tag.position.set(...position)
  tag.rotation.set(...rotation)
  group.add(tag);
  // addGUI(tag)
}


function createtvDom(obj) {
  console.log(obj,'obj111');
  const { position, rotation, targetAttr,tv,innerHTML,scale } = obj;
  const div = document.createElement('video');

  // const geometry1 = new THREE.PlaneGeometry(1, 0.5);
  div.src ='other/movie.mp4'
  div.muted = false;
  div.style.position = 'fixed';
  div.style.left = `0%`;
  div.style.top = `0%`;
  div.style.padding = `10px`;
  div.style.width = '80px';
  div.style.height = '80px';
  // div.style.backgroundColor = 'red';
  div.addEventListener('loadedmetadata',()=>{
    div.play();
    div.loop = true;
    tv(div)
  })
  const tag1 = new CSS3DObject(div);
  tag1.scale.set(...scale)
  tag1.position.set(...position)
  tag1.rotation.set(...rotation)
  group.add(tag1);
  // addGUI(tag1)
}




// 绑定点击事件
function bindClickEvent() {
  const rayCaster = new THREE.Raycaster()
  const pointer = new THREE.Vector2()
  window.addEventListener('click', (e) => {
    pointer.x = ( e.clientX / window.innerWidth ) * 2 - 1;
    pointer.y = - ( e.clientY / window.innerHeight ) * 2 + 1;

    rayCaster.setFromCamera( pointer, camera );
    const list = rayCaster.intersectObjects( scene.children );
    const item1 = list.find(item=>item.object.name === 'landmark')
    if (item1) {
      let targetObj = sceneInfoObj[item1.object.userData.attr];
      console.log(targetObj,'targetObj');
      setMaterialCube(targetObj);
    }
  })
}


const cubeObj = createcube();
setMaterialCube(sceneInfoObj.one);
bindClickEvent();

封装的init

csharp 复制代码
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
// 引入CSS3渲染器CSS3DRenderer
import {CSS3DRenderer} from 'three/addons/renderers/CSS3DRenderer.js';


// 全局变量
export let scene, camera, renderer, controls,css3Renderer ;

// 初始化函数
(function init() {
  // 创建场景
  scene = new THREE.Scene();
  // scene.background = new THREE.Color(0xffffff);

  // 创建相机
  camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
  camera.position.z = 0.1;

  // 创建渲染器
  renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  // 创建轨道控制器
  // controls = new OrbitControls(camera, renderer.domElement);
  // controls.enableDamping = true;
  // controls.dampingFactor = 0.05;
})();
(function createContols(){
  controls = new OrbitControls(camera, renderer.domElement);
})();

// (function createHelper(){
//   // 创建辅助坐标轴
//   const axesHelper = new THREE.AxesHelper(5);
//   scene.add(axesHelper);
// })();
// (function createGrid(){
//   // 创建网格辅助器
//   const gridHelper = new THREE.GridHelper(10, 10);
//   scene.add(gridHelper);
// })();

// 窗口大小改变时重新渲染
(function resizeRenderer() {
  window.addEventListener('resize', () => {
     renderer.setSize(window.innerWidth, window.innerHeight);
     camera.aspect = window.innerWidth / window.innerHeight;
     camera.updateProjectionMatrix();
  })
 
})();

(function create3Render(){
  css3Renderer = new CSS3DRenderer()
  css3Renderer.setSize(window.innerWidth, window.innerHeight);
  css3Renderer.domElement.style.position = 'fixed';
  css3Renderer.domElement.style.top = 0;
  css3Renderer.domElement.style.left = 0;
  css3Renderer.domElement.style.pointerEvents = 'none';
  document.body.appendChild(css3Renderer.domElement);
  
})();



// 渲染循环
(function renderLoop() {
  renderer.render(scene, camera);
  // css3Renderer.render(scene, camera);
  controls.update();
  css3Renderer.render(scene, camera);
  requestAnimationFrame(renderLoop);
})();

gui

csharp 复制代码
// 封装gui的工具,用来调整物体的位置和旋转的角度
import * as dat from 'dat.gui'
const gui = new dat.GUI()
export default function addGUI(obj) {
  gui.add(obj.position, 'x', -1, 1, 0.01).name('位置X')
  gui.add(obj.position, 'y', -1, 1, 0.01).name('位置Y')
  gui.add(obj.position, 'z', -1, 1, 0.01).name('位置Z')


  gui.add(obj.rotation, 'x', 0,2*Math.PI, 0.01).name('旋转X')
  gui.add(obj.rotation, 'y', 0,2*Math.PI, 0.01).name('旋转Y')
  gui.add(obj.rotation, 'z', 0,2*Math.PI, 0.01).name('旋转Z')
}
相关推荐
学Linux的语莫2 小时前
Vue前端知识
前端·javascript·vue.js
Cherry的跨界思维2 小时前
8、Python正则表达式精准搜索实战:从模糊匹配到精准定位
开发语言·python·正则表达式·django·flask·pygame·tornado
星释2 小时前
Rust 练习册 113:构建你自己的 CSV 处理器
开发语言·windows·rust
2401_860319522 小时前
【精通篇】打造React Native鸿蒙跨平台开发高级复合组件库开发系列:SwipeCell 滑动单元格(可以左右滑动来展示操作按钮的单元格组件)
javascript·react native·ecmascript
LYFlied2 小时前
前端开发者需要掌握的编译原理相关知识及优化点
前端·javascript·webpack·性能优化·编译原理·babel·打包编译
定义小花2 小时前
c++ cmake qt
开发语言·c++·qt
BlackWolfSky2 小时前
ES6 学习笔记3—7数值的扩展、8函数的扩展
前端·javascript·笔记·学习·es6
未来之窗软件服务2 小时前
幽冥大陆(四十四)源码找回之Vue——东方仙盟筑基期
前端·javascript·vue.js·仙盟创梦ide·东方仙盟·源码提取·源码丢失