做一个类似于https://my.matterportvr.cn/show/?m=WsQvZoxSg5d
这样的,可以点击选择进入某某房间查看和观看楼层平面图以及楼层选择器的网页:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AR导航</title>
<style>
*{
padding: 0;
margin: 0;
}
body{
overflow: hidden;
}
.btn-container{
position: absolute;
left: 10px;
top: 10px;
z-index: 10;
width: 100px;
display: flex;
justify-content: space-between;
}
.btn-container img{
height: 40px;
}
ul{
list-style: none;
}
li{
text-align: center;
padding: 5px 0px;
}
li:hover{
background-color: rgba(0,0,0,0.3);
cursor: pointer;
}
</style>
</head>
<body>
<div class="btn-container">
<img class="reset-btn" title="查看楼层平面图" @click='reset' src="./imgs/map.png" alt="">
<div class="layer-box">
<img class="layer-btn" title="楼层选择器" @click='toggleLayerShow' src="./imgs/layer.png" alt="">
<ul v-if = 'layerShow'>
<li v-for='(item,index) in layerData' v-bind:data-key='item.key' @click='selectLayer'>{{item.name}}</li>
</ul>
</div>
</div>
<div id="container"></div>
</body>
<script src="js/vue.js"></script>
<script src="js/three.js"></script>
<script src="js/loaders/GLTFLoader.js"></script>
<script src="js/OrbitControls.js"></script>
<script src="js/renderers/CSS2DRenderer.js"></script>
<script src="js/libs/Tween.js"></script>
<script>
(function(){
const gltfLoader = new GLTFLoader();
const modelUrl = 'https://houtaicdn.alva.com.cn/medias/resources/wechat/XiamenLieshi/model/GLTF3/XM.gltf';
let scene,camera,renderer,controls,model;
let sceneName = 'global';
const origin = new THREE.Vector3(0,0,5), direction = new THREE.Vector3(0,0,5).normalize();
let mouse = new THREE.Vector2(), raycaster = new THREE.Raycaster(origin, direction);
init();
// addHelper();
function init(){
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight, 0.1,1000);
camera.position.z = 5;
initControls();
// addResetBtn();
gltfLoader.load(modelUrl,function(gltf){
model = gltf.scene;
// model.position.set(0,-30,150);
model.scale.set(3,3,3);
model.rotation.set(1.5,0,0);
scene.add(model);
initLight();
});
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true,
preserveDrawingBuffer: true
});
renderer.setSize(window.innerWidth,window.innerHeight);
document.body.appendChild(renderer.domElement);
animate()
}
document.body.addEventListener('mousedown',onDown,false);
function onDown(event){
event.preventDefault();
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects(model.children);
if (intersects.length > 0 && sceneName === 'global') {// 如果点击到了某个房间,则进入此房间查看
const name = intersects[0].object.name;
console.log(name)
goPart(name);
}
}
function goPart(name){
if (sceneName === 'Ani') return;
sceneName = 'Ani';
var sName = '';
var tweenP = new TWEEN.Tween(model.position);// TWEEN过渡动画
var tweenS = new TWEEN.Tween(model.scale);
var tweenR = new TWEEN.Tween(model.rotation);
tweenS.to(new THREE.Vector3(300,300,300),3000);
tweenR.to(new THREE.Vector3(0,0,0), 1000);
tweenP.easing(TWEEN.Easing.Quadratic.InOut);
tweenS.easing(TWEEN.Easing.Quadratic.InOut);
tweenR.easing(TWEEN.Easing.Quadratic.InOut);
controls.reset();
switch(name){
case '房间1':// 正中
sName = 'center';
tweenP.to(new THREE.Vector3(0,40,0),3000);
break;
case '房间2':// 中左
sName = 'center-left';
tweenP.to(new THREE.Vector3(170,20,0),3000);
break;
case '房间3':// 中右
sName = 'center-right';
tweenP.to(new THREE.Vector3(-140,-30,0),3000);
break;
case '房间4':// 上左
sName = 'top-left';
tweenP.to(new THREE.Vector3(80,-30,150),3000);
break;
case '房间5':// 上右
name = 'top-right';
tweenP.to(new THREE.Vector3(-80,-30,150),3000);
break;
case '房间6':// 下
sName = 'bottom';
tweenP.to(new THREE.Vector3(0,0,-150),3000);
break;
}
// tweenP.delay(2000);
tweenP.start();
tweenS.start();
tweenR.start();
tweenP.onComplete(() => {
sceneName = sName;
})
}
function initLight(){
var aLight = new THREE.AmbientLight(0xffffff,0.2);
scene.add(aLight)
var dLight1 = new THREE.PointLight(0xffffff,1,100);
dLight1.position.set(0,60,0);
dLight1.target = model;
scene.add(dLight1);
var dLight2 = new THREE.PointLight(0xffffff,1,300);
dLight2.position.set(170,40,0);
dLight2.target = model;
var dLight3 = new THREE.PointLight(0xffffff,1,300);
dLight3.position.set(-140,-10,0);
dLight3.target = model;
scene.add(dLight3);
var dLight4 = new THREE.PointLight(0xffffff,1,300);
dLight4.position.set(80,-10,150);
dLight4.target = model;
scene.add(dLight4);
var dLight5 = new THREE.PointLight(0xffffff,1,300);
dLight5.position.set(0,20,-150);
dLight5.target = model;
scene.add(dLight5);
}
function animate(){
requestAnimationFrame(animate);
renderer.render(scene,camera);
TWEEN.update();
}
function initControls(){
controls = new THREE.OrbitControls(camera)
controls.enableZoom = true
//controls.autoRotate = true;
controls.minDistance = 3;
controls.maxDistance = 10;
controls.enablePan = false;
}
function addHelper(){
// var dir = new THREE.Vector3( 1, 2, 0 );
// dir.normalize();
// var origin = new THREE.Vector3( 0, 0, 0 );
// var length = 1;
// var hex = 0xffff00;
// var arrowHelper = new THREE.ArrowHelper( dir, origin, length, hex );
// scene.add( arrowHelper );
// 红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴.
var axesHelper = new THREE.AxesHelper(250);
scene.add(axesHelper);
}
function addResetBtn(){
let labelRenderer = new CSS2DRenderer('img');
labelRenderer.setSize( 60, 40 );
// labelRenderer.domElement.style.pointerEvents = 'none';// 禁用事件
labelRenderer.domElement.style.position = 'absolute';
labelRenderer.domElement.style.top = '10px';
labelRenderer.domElement.style.left = '10px';
labelRenderer.domElement.src = './imgs/map.png';
labelRenderer.domElement.alt = '平面图';
labelRenderer.domElement.title = '平面图';
labelRenderer.domElement.addEventListener('click',reset,false);
labelRenderer.render( scene, camera );
document.getElementById( 'container' ).appendChild( labelRenderer.domElement );
}
var vm = new Vue({
el: '.btn-container',
data: {
layerData:[
{name: '全部', key: '0'},
{name: '一楼', key: '1'},
{name: '二楼', key: '2'},
],
layerShow: false
},
methods:{
toggleLayerShow(){
this.layerShow = !this.layerShow;
},
selectLayer(e){
this.layerShow = !this.layerShow;
const { key } = e.srcElement.dataset;
camera.layers.mask = Number(key);// 修改显示的楼层
},
reset(){// 查看平面图
if (sceneName === 'Ani') return;
sceneName = 'Ani';
// model.position.set(0,0,0);
// model.scale.set(3,3,3);
// model.rotation.set(1.5,0,0);
controls.reset();
var tweenP = new TWEEN.Tween(model.position);
tweenP.to(new THREE.Vector3(0,0,0), 2000);
var tweenR = new TWEEN.Tween(model.rotation);
tweenR.to(new THREE.Vector3(1.5,0,0), 2000);
var tweenS = new TWEEN.Tween(model.scale);
tweenS.to(new THREE.Vector3(3,3,3), 2000);
tweenP.easing(TWEEN.Easing.Quadratic.InOut);
tweenS.easing(TWEEN.Easing.Quadratic.InOut);
tweenR.easing(TWEEN.Easing.Quadratic.InOut);
tweenP.start();
tweenR.start();
tweenS.start();
tweenP.onComplete(() => {
sceneName = 'global';
})
}
}
});
})()
</script>
</html>