思路 ,创建盒子 ,前进按钮, 第一次进去创建一个盒子 盒子上添加图片纹理
也就是天空盒子一样的
在创建 一个面 设置好对应的角度和位置
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')
}