- <template>
- <!-- 项目模型实景管理 -->
- <div class="projectModalM">
- <div id="QuanJing" ref="threeDom" v-if="ifHasUrl" v-loading="modalLoading"></div>
- <!-- 暂无数据 -->
- <div v-else class="noData">暂无全景图片</div>
- </div>
- </template>
-
- <script setup>
- import * as THREE from 'three';
- import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'; //控制器
- import gsap from 'gsap';
- import { CSSRulePlugin } from 'gsap/CSSRulePlugin';
- import bus from '@/bus';
- const { proxy } = getCurrentInstance();
- gsap.registerPlugin(CSSRulePlugin); // 引入css插件,完成某些css动画
-
- const AllData = ref({
- show: false,
- numer: '0%',
- imgUrl: '', //渲染的目标图片
- imgWidth: 1200, //渲染宽度px
- imgHeight: 560, //渲染高度px
- });
- const ifHasUrl = ref(true);
- const modalLoading = ref(true);
-
- // 初始化模型
- const SceneModal = new THREE.Scene();
- const CameraModal = new THREE.PerspectiveCamera(30, AllData.value.imgWidth / AllData.value.imgHeight, 0.1, 5000);
- const Renderer = new THREE.WebGLRenderer({
- antialias: true,
- alpha: true, //开启alpha
- });
- // 控制器
- const Controls = new OrbitControls(CameraModal, Renderer.domElement);
-
- // 注意:此处为threejs的DOM,需要将threejs的场景渲染进去
- const threeDom = ref();
-
- // 首页进入相机的视角,这个视角可以在三维模型中建立一个摄像机获取摄像机的坐标,如C4D,非常准确.
- const cameraPosition = {
- x: 500,
- y: 400,
- z: -200,
- };
- const cameraLookat = {
- x: 0,
- y: 0,
- z: 0,
- };
- // 声明一个方法传入参数可以在不同的地方调用相机
- const cameraReset = (position, lookAt, time = 1) => {
- gsap.to(CameraModal.position, {
- x: position.x,
- y: position.y,
- z: position.z,
- duration: time,
- ease: 'power4.out',
- // onComplete: function () {
- // 这是相机运动完成的回调,可以执行其他的方法.
- // }
- });
- gsap.to(CameraModal.lookAt, {
- x: lookAt.x,
- y: lookAt.y,
- z: lookAt.z,
- duration: time,
- ease: 'power4.out',
- });
- gsap.to(CameraModal.target, {
- x: lookAt.x,
- y: lookAt.y,
- z: lookAt.z,
- duration: time,
- ease: 'power4.out',
- });
- };
-
- const initThreeScene = () => {
- // 使动画循环使用时阻尼或自转 意思是否有惯性
- Controls.enableDamping = true;
- // 动态阻尼系数 就是鼠标拖拽旋转灵敏度
- Controls.dampingFactor = 0.1;
- // 是否可以旋转
- Controls.enableRotate = true;
- // 是否可以缩放与速度
- Controls.enableZoom = true;
- // 设置相机距离原点的最远距离
- // Controls.minDistance = 1;
- // 设置相机距离原点的最远距离
- Controls.maxDistance = 900;
- Controls.autoRotate = true;
- Controls.autoRotateSpeed = 1.0;
-
- // 是否开启右键拖拽
- Controls.enablePan = false;
- // Controls.addEventListener("change", render);
- //render的相关设置
- // Renderer.setPixelRatio(window.devicePixelRatio);
- Renderer.setSize(AllData.value.imgWidth, AllData.value.imgHeight);
- Renderer.inputEncoding = true;
- // Renderer.outputEncoding = THREE.sRGBEncoding;
- // Renderer.setClearColor(0xd0d0d0, 1);
- // 将renderer渲染进DOM里面
- threeDom.value.appendChild(Renderer.domElement);
- };
- // 设置页面自适应
- const onWindowResize = () => {
- CameraModal.aspect = AllData.value.imgWidth / AllData.value.imgHeight;
- CameraModal.updateProjectionMatrix();
- Renderer.setSize(AllData.value.imgWidth, AllData.value.imgHeight);
- };
- window.addEventListener('resize', onWindowResize, false);
- // 完成以上步骤基本的场景已经配置完成
-
- cameraReset(cameraPosition, cameraLookat);
-
- const Render = () => {
- requestAnimationFrame(Render);
- Controls.update(); // 轨道控制器的更新
- Renderer.clear(); // 清除画布
- Renderer.render(SceneModal, CameraModal);
- };
-
- // 初始化加载模型
- function initModal(imgUrl) {
- modalLoading.value = true;
- let event = {};
- // 单张纹理图的加载
- event.onLoad = function () {
- console.log('图片加载完成');
- AllData.value.show = false;
- modalLoading.value = false;
- };
- event.onProgress = function (url, num, total) {
- console.log('图片加载完成:', url);
- console.log('图片加载进度:', num);
- console.log('图片总数:', total);
- let value = ((num / total) * 100).toFixed(2) + '%';
- console.log('加载进度的百分比:', value);
- AllData.value.numer = value;
- modalLoading.value = false;
- };
- event.onError = function (e) {
- console.log('图片加载出现错误');
- console.log(e);
- AllData.value.show = false;
- modalLoading.value = false;
- };
- // 设置加载管理器
- const loadingManager = new THREE.LoadingManager(event.onLoad, event.onProgress, event.onError);
- const textureLoader = new THREE.TextureLoader(loadingManager);
- var material = new THREE.MeshBasicMaterial(); //材质
- var texture = textureLoader.load(imgUrl);
- material.map = texture;
- // var skyBox = new THREE.Mesh(new THREE.SphereBufferGeometry(600, 600, 600), material);
- var skyBox = new THREE.Mesh(new THREE.SphereGeometry(600, 600, 600), material);
- skyBox.geometry.scale(1, 1, -1);
- SceneModal.add(skyBox);
- }
- onMounted(() => {
- bus.on('getProjectDate', v => {
- ifHasUrl.value = v.projectpicture.length > 0 ? true : false;
- if (ifHasUrl.value) {
- initModal(v.projectpicture[0].url); //初始化
- initThreeScene();
- Render();
- }
- });
- });
- onBeforeUnmount(() => {
- SceneModal.remove(skyBox); //删除组
- SceneModal = null;
- });
- </script>
-
- <style lang="scss" scoped>
- .projectModalM {
- #QuanJing {
- width: 100%;
- height: 100%;
- }
- .noData {
- font-size: 20px;
- text-align: center;
- margin-top: 10%;
- color: #fff;
- }
- }
- </style>