|
@@ -0,0 +1,318 @@
|
|
|
+<template src="./mapComponent.html"></template>
|
|
|
+<script>
|
|
|
+ import * as THREE from 'three';
|
|
|
+ import Stats from 'three/addons/libs/stats.module.js';
|
|
|
+ import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
|
|
|
+ import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
|
|
|
+
|
|
|
+ import TWEEN from 'three/addons/libs/tween.module.js';
|
|
|
+
|
|
|
+ var requestId = "";
|
|
|
+ // const util = require('@/static/utils/util.js');
|
|
|
+ const config = require('@/services/urlConfig.js');
|
|
|
+ export default {
|
|
|
+ /**
|
|
|
+ * 页面的初始数据
|
|
|
+ */
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ pvCurPageName: "home_show",
|
|
|
+ locusBehaviorName: "主界面",
|
|
|
+ pvCurPageParams: null,
|
|
|
+ houseId: "100296",
|
|
|
+ pvId: 'p_2cmina_23080401',
|
|
|
+ canvas:null,
|
|
|
+ navbar: {
|
|
|
+ showCapsule: 1,
|
|
|
+ title: '',
|
|
|
+ titleColor: '#000',
|
|
|
+ navPadding: 0,
|
|
|
+ navPaddingBg:'transparent',
|
|
|
+ navBarColor: 'transparent',
|
|
|
+ navBackColor: 'transparent',
|
|
|
+ haveCallback: false,
|
|
|
+ fromShare: false,
|
|
|
+ fromProject: 0,
|
|
|
+ shareToken: "",
|
|
|
+ pageName: this.pvCurPageName,
|
|
|
+ },
|
|
|
+ loader:null,
|
|
|
+ scene:null,
|
|
|
+ sky:null,
|
|
|
+ camera:null,
|
|
|
+ houseList:[], //当前户型所有的户型详情,可以切换
|
|
|
+ curHouseType: null, //当前选中的户型类型
|
|
|
+ curHouseName:'',//当前选中的户型类型名称
|
|
|
+ curHouseFloor: null, //当前选中的户型楼层
|
|
|
+ curHouseObj: null,
|
|
|
+ controlStarPosition : { x:0, y:0, z:0}, //控制器初始位置
|
|
|
+ cameraStarPosition : { x:0, y:20, z:0} ,//摄像头初始位置
|
|
|
+ // cameraLastPosition: null, //摄像头上一次移动到的位置
|
|
|
+ // controlLastPosition: null, //观察点上一次移动到的位置
|
|
|
+ // canvasHeight:200, //canvas视图的高度-计算得出
|
|
|
+ chooseMesh:null,//标记鼠标拾取到的mesh
|
|
|
+ // chooseMeshColor:'', //拾取到的mesh的原始颜色;
|
|
|
+ chooseWallMeshColor:'', // 拾取墙体原始颜色
|
|
|
+ curWallArr:[], // 当前空间选中墙面的墙体模型
|
|
|
+ isManyou: false, //当前是否处在漫游状态
|
|
|
+ pageShowIndex: 2, // 默认户型列表页面
|
|
|
+ aleadyLoaderModel:[], //已经加载的墙体元数据模型列表
|
|
|
+ // fontLabelGroup: [],
|
|
|
+ shottingImg: [],
|
|
|
+ progress:1, //进度条
|
|
|
+ myLoadingStatus:false,
|
|
|
+ // textGeoList:[],
|
|
|
+ repeatFlag:false, //重复点击
|
|
|
+ skyPlan: null, // 天空盒子
|
|
|
+
|
|
|
+ gltfLayouts:[], // 场景中墙体模型数组
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onUnload() {
|
|
|
+ cancelAnimationFrame(requestId, this.canvas)
|
|
|
+ this.worker && this.worker.terminate()
|
|
|
+ setTimeout(() => {
|
|
|
+ if (this.renderer instanceof THREE.WebGLRenderer) {
|
|
|
+ this.renderer.dispose()
|
|
|
+ this.renderer.forceContextLoss()
|
|
|
+ this.renderer.context = null
|
|
|
+ this.renderer.domElement = null
|
|
|
+ this.renderer = null;
|
|
|
+ this.clearEvent()
|
|
|
+ }
|
|
|
+ this.gltfWalls = [];
|
|
|
+ this.gltfSpaces = [];
|
|
|
+ this.instancedMeshList = [];
|
|
|
+ this.instancedSpaceMeshList = [];
|
|
|
+ this.lableItem = [];
|
|
|
+ this.gltfLayouts = [];
|
|
|
+ this.instancedFurList = [];
|
|
|
+ this.wallList = [];
|
|
|
+ TWEEN && TWEEN.removeAll();//清除所有的tween;
|
|
|
+ }, 0)
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+
|
|
|
+
|
|
|
+ var that = this;
|
|
|
+ const container = this.$refs.webgl;
|
|
|
+ const canvas3d = this.canvas = this.$refs.glcanvas;
|
|
|
+
|
|
|
+ let camera = null, renderer = null, controls=null;
|
|
|
+ // let trackballControls = null;
|
|
|
+ console.warn("***loader0***",this.loader)
|
|
|
+ let loader = null;
|
|
|
+ loader = this.loader = new GLTFLoader();
|
|
|
+ // if(this.childLayout){
|
|
|
+ // this.getInitData();//请求获取页面模型数据等
|
|
|
+ // }
|
|
|
+ let scene = this.scene = new THREE.Scene();
|
|
|
+ let isUserContorl = false;
|
|
|
+ let tweenCameraAnma = false; //表示当前是否处在动画过程中
|
|
|
+ let needRender = false; //是否需要渲染 false表示不需要渲染;true 表示需要渲染
|
|
|
+ let frustumSize = 30;//正交相机的视窗宽度距离
|
|
|
+ let stats;
|
|
|
+ let gltfLists = [];
|
|
|
+ let objects = [];
|
|
|
+ var mouse = new THREE.Vector2();
|
|
|
+ init();
|
|
|
+ // render();
|
|
|
+ // this.$refs.myLoading.showLoading("加载中..." + this.progress+"%")
|
|
|
+ // this.myLoadingStatus = true;
|
|
|
+
|
|
|
+ function init() {
|
|
|
+
|
|
|
+ scene.background = new THREE.Color("#FFFFFF");
|
|
|
+ // scene.environment = new THREE.Color("#F2F2F2");
|
|
|
+
|
|
|
+ // 创建相机位置-投影相机
|
|
|
+ camera = new THREE.PerspectiveCamera( 80, window.innerWidth / window.innerHeight, 0.1, 10000 );
|
|
|
+ // let aspect = window.innerWidth / window.innerHeight;
|
|
|
+ // camera = new THREE.OrthographicCamera( frustumSize * aspect / - 2, frustumSize * aspect / 2, frustumSize / 2, frustumSize / - 2, 0.1,1000);
|
|
|
+ camera.up.set(0, 1, 0);//俯视状态,将相机的up向量设置为z轴负方向
|
|
|
+ // camera.position.set(that.cameraStarPosition.x, that.cameraStarPosition.y, that.cameraStarPosition.z);
|
|
|
+ camera.position.set(0.1,15,0);
|
|
|
+ scene.add(camera);
|
|
|
+ that.camera = camera;
|
|
|
+ // 辅助方格
|
|
|
+ // const axesHelper = new THREE.AxesHelper( 50 );
|
|
|
+ // scene.add( axesHelper );
|
|
|
+ // const gridHelper = new THREE.GridHelper(50, 10, 0xcccccc, 0xcccccc);
|
|
|
+ // gridHelper.position.y = 0;
|
|
|
+ // gridHelper.position.x = 0;
|
|
|
+ // scene.add(gridHelper);
|
|
|
+
|
|
|
+ // 环境光会均匀的照亮场景中的所有物体
|
|
|
+ const ambientLight = new THREE.AmbientLight(0xFFEFE0, 2);
|
|
|
+ scene.add(ambientLight);
|
|
|
+ //平行光
|
|
|
+ const light = new THREE.DirectionalLight(0xFFF8E5, 2.2);
|
|
|
+ light.position.set(-14.8, 9.188, -7.448); //default; light shining from top
|
|
|
+ scene.add(light);
|
|
|
+ // 从一个点向各个方向发射的光源。一个常见的例子是模拟一个灯泡发出的光。
|
|
|
+ // const pointLight = new THREE.PointLight( 0xffffff, 0.3 );
|
|
|
+ // camera.add( pointLight );
|
|
|
+
|
|
|
+
|
|
|
+ //antialias 这个值得设置为false,不然IOS上截图会失效
|
|
|
+ renderer = that.renderer = new THREE.WebGLRenderer( { canvas:canvas3d, alpha: true, antialias:false,
|
|
|
+ // 如果想保存three.js canvas画布上的信息,注意设置preserveDrawingBuffer
|
|
|
+ preserveDrawingBuffer: true, } );
|
|
|
+ renderer.shadowMap.enabled = true;//产生阴影
|
|
|
+ renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 阴影属性
|
|
|
+ renderer.outputEncoding = THREE.sRGBEncoding;
|
|
|
+ renderer.outputColorSpace = THREE.SRGBColorSpace;
|
|
|
+ // renderer.toneMappingExposure = 0.1;//色调映射的曝光级别。默认是1
|
|
|
+ renderer.toneMapping = THREE.NoToneMapping;//色调映射
|
|
|
+ renderer.physicallyCorrectLights = true;//关键参数,模拟物理光照影响,必须设置为true
|
|
|
+
|
|
|
+ renderer.setPixelRatio( window.devicePixelRatio );
|
|
|
+ renderer.setSize( window.innerWidth, window.innerHeight );
|
|
|
+ container.appendChild( renderer.domElement );
|
|
|
+
|
|
|
+ controls = new OrbitControls(camera, renderer.domElement);
|
|
|
+ controls.screenSpacePanning = true;
|
|
|
+ controls.enableDamping = true;
|
|
|
+ controls.minDistance = 1;
|
|
|
+ controls.maxDistance = 400;
|
|
|
+ controls.minPolarAngle = 0;// 默认0
|
|
|
+ controls.maxPolarAngle = Math.PI / 2; // 默认Math.PI,即可以向下旋转到的视角。
|
|
|
+ controls.target.set(that.controlStarPosition.x, that.controlStarPosition.y, that.controlStarPosition.z);
|
|
|
+ controls.enableZoom = true;//启用摄像机的缩放
|
|
|
+
|
|
|
+ // that.controls = controls;
|
|
|
+ // controls.target = new THREE.Vector3( that.controlStarPosition.x, that.controlStarPosition.y, that.controlStarPosition.z );;
|
|
|
+ camera.lookAt(0,0,0);
|
|
|
+ // 监听
|
|
|
+ // renderer.domElement.addEventListener('resize', onWindowResize );
|
|
|
+ stats = new Stats();
|
|
|
+ container.appendChild( stats.dom );
|
|
|
+ // attendEvent(); //注册监听事件
|
|
|
+ starRender(); //启动渲染
|
|
|
+ // 监听
|
|
|
+ // window.addEventListener( 'resize', onWindowResize );
|
|
|
+ let arr = [
|
|
|
+ {url: 'https://dm.static.elab-plus.com/3d/model/11-28/%E5%B7%A5%E4%BD%9C%E5%AD%A6%E4%B9%A0-%E7%9B%B4%E6%8E%A5.glb', name: '工作学习模块', positionX: 3, positionY: 0, positionZ:-1.5, rotation: (270 * ( Math.PI / 180 )),},
|
|
|
+ {url: 'https://dm.static.elab-plus.com/3d/model/11-28/%E7%9D%A1%E7%9C%A0-%E9%97%B4%E6%8E%A5.glb', name: '睡眠模块', positionX: 6, positionY: 0, positionZ:1.5, rotation: (180 * ( Math.PI / 180 )),},
|
|
|
+ {url: 'https://dm.static.elab-plus.com/3d/model/11-28/%E5%AE%A0%E7%89%A9-%E6%A0%B8%E5%BF%83.glb', name: '宠物模块', positionX: -3, positionY: 0, positionZ:1.5, rotation:0,},
|
|
|
+ {url: 'https://dm.static.elab-plus.com/3d/model/11-28/%E4%BC%91%E9%97%B2-%E7%9B%B4%E6%8E%A5.glb', name: '休闲模块', positionX: 3, positionY: 0, positionZ:1.5, rotation: (180 * ( Math.PI / 180 )),},
|
|
|
+ {url: 'https://dm.static.elab-plus.com/3d/model/11-28/%E5%BD%B1%E9%9F%B3-%E7%9B%B4%E6%8E%A5.glb', name: '影音模块', positionX: 0, positionY: 0, positionZ:1.5, rotation: (180 * ( Math.PI / 180 )),},
|
|
|
+ {url: 'https://dm.static.elab-plus.com/3d/model/11-28/%E6%B4%97%E6%B5%B4-%E9%97%B4%E6%8E%A5.glb', name: '洗浴模块', positionX: -3, positionY: 0, positionZ:3.5, rotation: (90 * ( Math.PI / 180 )),},
|
|
|
+ {url: 'https://dm.static.elab-plus.com/3d/model/11-28/%E6%94%B6%E7%BA%B3-%E9%97%B4%E6%8E%A5.glb', name: '收纳模块', positionX: -3, positionY: 0, positionZ:1.5, rotation: (90 * ( Math.PI / 180 )),},
|
|
|
+ {url: 'https://dm.static.elab-plus.com/3d/model/11-28/%E5%AE%B6%E6%94%BF-%E9%97%B4%E6%8E%A5.glb', name: '家政模块', positionX: -6, positionY: 0, positionZ:-1.5, rotation: 0,},
|
|
|
+ ];
|
|
|
+ arr.forEach((item,index) =>{
|
|
|
+ loaderArr(item,index)
|
|
|
+ })
|
|
|
+ }
|
|
|
+ function loaderArr(item,index){
|
|
|
+ loader.load( item.url, ( gltf ) => {
|
|
|
+ //将模型添加到场景中
|
|
|
+ var cube = gltf.scene;
|
|
|
+ var mesh = cube.children[0];
|
|
|
+ cube.name= item.name;
|
|
|
+ scene.add(cube);
|
|
|
+ cube.rotation.y = item.rotation;
|
|
|
+ cube.position.set(item.positionX,item.positionY,item.positionZ);
|
|
|
+
|
|
|
+ // cube.userData.obb = new OBB();
|
|
|
+ // cube.userData.obb = new OBB();
|
|
|
+ // cube.userData.obb.halfSize.copy( size ).multiplyScalar( 0.5 );
|
|
|
+ console.warn("***gltf-geometry" + index + "***",gltf)
|
|
|
+ gltfLists.push(cube);
|
|
|
+
|
|
|
+ // let obb = new OBB();
|
|
|
+ // obb.halfSize.copy( size ).multiplyScalar( 0.5 );
|
|
|
+
|
|
|
+ let box = new THREE.BoxHelper(cube,'rgba(0,0,0,0)');
|
|
|
+ box.name = item.name;
|
|
|
+ console.warn("***WireframeGeometry-geometry***",box)
|
|
|
+ scene.add(box);
|
|
|
+ var material = new THREE.MeshBasicMaterial({
|
|
|
+ transparent:true,
|
|
|
+ opacity:0.6
|
|
|
+
|
|
|
+ });
|
|
|
+ // material.wireframe = true;
|
|
|
+ var mesh = new THREE.Mesh(box.geometry,material);
|
|
|
+ scene.add(mesh);
|
|
|
+ objects.push(box);
|
|
|
+ } );
|
|
|
+ }
|
|
|
+ function onWindowResize() {
|
|
|
+ camera.aspect = window.innerWidth / window.innerHeight;
|
|
|
+ camera.updateProjectionMatrix();
|
|
|
+ renderer.setSize( window.innerWidth, window.innerHeight );
|
|
|
+ console.warn("****onWindowResize**")
|
|
|
+ }
|
|
|
+ function attendEvent () {
|
|
|
+ document.addEventListener('touchstart', onPointerStart, false);
|
|
|
+ document.addEventListener('touchmove', onPointerMove, false);
|
|
|
+ document.addEventListener('touchend', onPointerUp, false);
|
|
|
+ }
|
|
|
+ function tweenCameraAnmaChange (value) {
|
|
|
+ tweenCameraAnma = value
|
|
|
+ }
|
|
|
+ //开启渲染-帧率优化,不触发时停止渲染
|
|
|
+ function enableRender() {
|
|
|
+ }
|
|
|
+ //取消事件监听-避免二次进入时触发多次事件
|
|
|
+ function clearEvent(){
|
|
|
+ console.warn("**clearEvent****")
|
|
|
+ document.removeEventListener('touchstart', onPointerStart);
|
|
|
+ document.removeEventListener('touchmove', onPointerMove );
|
|
|
+ document.removeEventListener('touchend', onPointerUp );
|
|
|
+ }
|
|
|
+ function stopRender () {
|
|
|
+ needRender = false;
|
|
|
+ }
|
|
|
+ function starRender () {
|
|
|
+ if(needRender==true){//如果已经在渲染中了,则不能再次开启,避免渲染过多
|
|
|
+ false;
|
|
|
+ }
|
|
|
+ needRender = true;
|
|
|
+ render();//开始渲染
|
|
|
+ }
|
|
|
+ function render() {
|
|
|
+ if(needRender==false){
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ TWEEN && TWEEN.update();
|
|
|
+ stats.update();
|
|
|
+ //不处在动画过程中,则可以处理移动等动作
|
|
|
+ if(tweenCameraAnma==false){
|
|
|
+ controls.update();
|
|
|
+ }
|
|
|
+ requestId = requestAnimationFrame(render, canvas3d);
|
|
|
+ renderer.render(scene, camera);//单次渲染
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onShow(){
|
|
|
+ if(this.attendEvent){
|
|
|
+ this.attendEvent()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onHide(){
|
|
|
+ this.clearEvent();
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ onMouseMove(e){
|
|
|
+ return false;
|
|
|
+ },
|
|
|
+ webgl_touch(e) {
|
|
|
+ const web_e = Event.fix(e)
|
|
|
+ window.dispatchEvent(web_e)
|
|
|
+ let web_e2 = Object.assign(e,web_e)
|
|
|
+ document.dispatchEvent(web_e2)
|
|
|
+ this.canvas.dispatchEvent(web_e)
|
|
|
+ },
|
|
|
+ changCarmer(){
|
|
|
+ this.camera.position.set(-0.1,15,0);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+</script>
|
|
|
+<style lang="css" scoped>
|
|
|
+ @import "./mapComponent.css";
|
|
|
+</style>
|