From fd9a2a05829f84dd3925da8fabec901498ebb9e0 Mon Sep 17 00:00:00 2001 From: ZhangXianQiang <1135831638@qq.com> Date: 星期五, 29 三月 2024 16:44:44 +0800 Subject: [PATCH] chore:重构场景 --- src/views/screen/components/screen-map-three/experience/camera.js | 44 +++++ src/views/screen/components/screen-map-three/experience/index.js | 39 ++++ /dev/null | 29 --- src/views/screen/components/screen-map-three/experience/utils/sizes.js | 33 ++++ src/views/screen/components/screen-map-three/experience/world/test.js | 24 +++ src/views/screen/components/screen-map-three/experience/world/world.js | 16 ++ src/views/screen/components/screen-wrapper/index.vue | 6 src/views/screen/components/screen-map-three/experience/utils/eventEmitter.js | 197 ++++++++++++++++++++++++ src/views/screen/components/screen-map-three/index.vue | 14 + src/views/screen/index.vue | 4 src/views/screen/components/screen-map-three/experience/renderer.js | 32 ++++ src/views/screen/components/screen-map-three/experience/utils/time.js | 25 +++ 12 files changed, 425 insertions(+), 38 deletions(-) diff --git a/src/views/screen/components/screen-map-three/experience/camera.js b/src/views/screen/components/screen-map-three/experience/camera.js new file mode 100644 index 0000000..70f33ff --- /dev/null +++ b/src/views/screen/components/screen-map-three/experience/camera.js @@ -0,0 +1,44 @@ +import { PerspectiveCamera, CameraHelper } from 'three'; +import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'; + + +export default class Camera { + constructor(experience) { + this.experience = experience; + this.scene = this.experience.scene; + this.canvas = this.experience.canvas; + this.sizes = this.experience.sizes; + this.setInstance(); + this.setOrbitControls(); + + } + + // 璁剧疆閫忚鐩告満 + setInstance() { + this.instance = new PerspectiveCamera(75,this.sizes.width / this.sizes.height, 0.1, 1000); + this.instance.position.set(0, 5, 2); + this.scene.add(this.instance); + const help = new CameraHelper(this.instance); + this.scene.add(help); + } + + setOrbitControls() { + this.controls = new OrbitControls(this.instance, this.canvas); + this.controls.target.set(0, 0, 0); + } + + resize() { + // 閲嶆柊璁$畻姣斾緥 + this.cameraAspect = (this.sizes.width / this.sizes.height) * this.frustrum; + this.instance.left = -this.cameraAspect / 2; + this.instance.right = this.cameraAspect / 2; + this.instance.top = this.frustrum / 2; + this.instance.bottom = -this.frustrum / 2; + this.instance.updateProjectionMatrix(); + } + + + update() { + this.controls.update(); + } +} \ No newline at end of file diff --git a/src/views/screen/components/screen-map-three/experience/index.js b/src/views/screen/components/screen-map-three/experience/index.js new file mode 100644 index 0000000..85dc8ca --- /dev/null +++ b/src/views/screen/components/screen-map-three/experience/index.js @@ -0,0 +1,39 @@ +import { Scene,GridHelper } from 'three'; + + +import World from "./world/world"; +import Camera from "./camera"; +import Renderer from "./renderer"; + +// 宸ュ叿绫� +import Sizes from "./utils/sizes"; +import Time from "./utils/time"; + +export default class Experience { + constructor(canvas) { + this.canvas = canvas; + this.sizes = new Sizes(); + this.time = new Time(); + this.scene = new Scene(); + this.camera = new Camera(this); + this.renderer = new Renderer(this); + this.world = new World(this); + + const size = 10; + const divisions = 10; + + const gridHelper = new GridHelper(size, divisions); + this.scene.add(gridHelper); + + // 甯� + this.time.on('tick', () => { + this.update(); + }); + } + + update() { + this.camera.update(); + this.world.update(); + this.renderer.update(); + } +} \ No newline at end of file diff --git a/src/views/screen/components/screen-map-three/experience/renderer.js b/src/views/screen/components/screen-map-three/experience/renderer.js new file mode 100644 index 0000000..3e7893c --- /dev/null +++ b/src/views/screen/components/screen-map-three/experience/renderer.js @@ -0,0 +1,32 @@ +import * as THREE from 'three'; +export default class Renderer { + constructor(experience) { + this.experience = experience; + this.canvas = this.experience.canvas; + this.sizes = this.experience.sizes; + this.scene = this.experience.scene; + this.camera = this.experience.camera; + + this.setInstance(); + } + setInstance() { + this.instance = new THREE.WebGLRenderer({ + canvas: this.canvas, + antialias: true, + alpha: true + }); + this.instance.toneMapping = THREE.CineonToneMapping; + this.instance.toneMappingExposure = 1.75; + this.instance.shadowMap.enabled = true; + this.instance.shadowMap.type = THREE.PCFSoftShadowMap; + this.instance.setSize(this.sizes.width, this.sizes.height); + this.instance.setPixelRatio(this.sizes.pixelRatio); + } + resize() { + this.instance.setSize(this.sizes.width, this.sizes.height); + this.instance.setPixelRatio(this.sizes.pixelRatio); + } + update() { + this.instance.render(this.scene, this.camera.instance); + } +} \ No newline at end of file diff --git a/src/views/screen/components/screen-map-three/experience/utils/eventEmitter.js b/src/views/screen/components/screen-map-three/experience/utils/eventEmitter.js new file mode 100644 index 0000000..216b423 --- /dev/null +++ b/src/views/screen/components/screen-map-three/experience/utils/eventEmitter.js @@ -0,0 +1,197 @@ +export default class EventEmitter +{ + constructor() + { + this.callbacks = {} + this.callbacks.base = {} + } + + on(_names, callback) + { + // Errors + if(typeof _names === 'undefined' || _names === '') + { + console.warn('wrong names') + return false + } + + if(typeof callback === 'undefined') + { + console.warn('wrong callback') + return false + } + + // Resolve names + const names = this.resolveNames(_names) + + // Each name + names.forEach((_name) => + { + // Resolve name + const name = this.resolveName(_name) + + // Create namespace if not exist + if(!(this.callbacks[ name.namespace ] instanceof Object)) + this.callbacks[ name.namespace ] = {} + + // Create callback if not exist + if(!(this.callbacks[ name.namespace ][ name.value ] instanceof Array)) + this.callbacks[ name.namespace ][ name.value ] = [] + + // Add callback + this.callbacks[ name.namespace ][ name.value ].push(callback) + }) + + return this + } + + off(_names) + { + // Errors + if(typeof _names === 'undefined' || _names === '') + { + console.warn('wrong name') + return false + } + + // Resolve names + const names = this.resolveNames(_names) + + // Each name + names.forEach((_name) => + { + // Resolve name + const name = this.resolveName(_name) + + // Remove namespace + if(name.namespace !== 'base' && name.value === '') + { + delete this.callbacks[ name.namespace ] + } + + // Remove specific callback in namespace + else + { + // Default + if(name.namespace === 'base') + { + // Try to remove from each namespace + for(const namespace in this.callbacks) + { + if(this.callbacks[ namespace ] instanceof Object && this.callbacks[ namespace ][ name.value ] instanceof Array) + { + delete this.callbacks[ namespace ][ name.value ] + + // Remove namespace if empty + if(Object.keys(this.callbacks[ namespace ]).length === 0) + delete this.callbacks[ namespace ] + } + } + } + + // Specified namespace + else if(this.callbacks[ name.namespace ] instanceof Object && this.callbacks[ name.namespace ][ name.value ] instanceof Array) + { + delete this.callbacks[ name.namespace ][ name.value ] + + // Remove namespace if empty + if(Object.keys(this.callbacks[ name.namespace ]).length === 0) + delete this.callbacks[ name.namespace ] + } + } + }) + + return this + } + + trigger(_name, _args) + { + // Errors + if(typeof _name === 'undefined' || _name === '') + { + console.warn('wrong name') + return false + } + + let finalResult = null + let result = null + + // Default args + const args = !(_args instanceof Array) ? [] : _args + + // Resolve names (should on have one event) + let name = this.resolveNames(_name) + + // Resolve name + name = this.resolveName(name[ 0 ]) + + // Default namespace + if(name.namespace === 'base') + { + // Try to find callback in each namespace + for(const namespace in this.callbacks) + { + if(this.callbacks[ namespace ] instanceof Object && this.callbacks[ namespace ][ name.value ] instanceof Array) + { + this.callbacks[ namespace ][ name.value ].forEach(function(callback) + { + result = callback.apply(this, args) + + if(typeof finalResult === 'undefined') + { + finalResult = result + } + }) + } + } + } + + // Specified namespace + else if(this.callbacks[ name.namespace ] instanceof Object) + { + if(name.value === '') + { + console.warn('wrong name') + return this + } + + this.callbacks[ name.namespace ][ name.value ].forEach(function(callback) + { + result = callback.apply(this, args) + + if(typeof finalResult === 'undefined') + finalResult = result + }) + } + + return finalResult + } + + resolveNames(_names) + { + let names = _names + names = names.replace(/[^a-zA-Z0-9 ,/.]/g, '') + names = names.replace(/[,/]+/g, ' ') + names = names.split(' ') + + return names + } + + resolveName(name) + { + const newName = {} + const parts = name.split('.') + + newName.original = name + newName.value = parts[ 0 ] + newName.namespace = 'base' // Base namespace + + // Specified namespace + if(parts.length > 1 && parts[ 1 ] !== '') + { + newName.namespace = parts[ 1 ] + } + + return newName + } +} \ No newline at end of file diff --git a/src/views/screen/components/screen-map-three/experience/utils/sizes.js b/src/views/screen/components/screen-map-three/experience/utils/sizes.js new file mode 100644 index 0000000..af7c98d --- /dev/null +++ b/src/views/screen/components/screen-map-three/experience/utils/sizes.js @@ -0,0 +1,33 @@ +/** + * 璁$畻澶у皬 + */ +import EventEmitter from './eventEmitter'; +export default class Sizes extends EventEmitter { + constructor() { + super(); + this.width = document.body.clientWidth; + this.height = document.body.clientHeight; + this.device = document.body.clientWidth <= 968 ? 'mobile' : 'pc'; + // 璁惧鍍忕礌 + this.pixelRatio = Math.min(window.devicePixelRatio, 2); + + // 瀹介珮鍙樺寲 + window.addEventListener('resize', () => { + // this.width = window.innerWidth; + // this.height = window.innerHeight; + + this.width = document.body.clientWidth; + this.height = document.body.clientHeight; + this.pixelRatio = Math.min(window.devicePixelRatio, 2); + this.trigger('resize'); + + if(this.width < 968 && this.device !== 'mobile') { + this.device = 'mobile'; + this.trigger('devicechange'); + } else if(this.width >= 968 && this.device !== 'pc') { + this.device = 'pc'; + this.trigger('devicechange'); + } + }); + } +} \ No newline at end of file diff --git a/src/views/screen/components/screen-map-three/experience/utils/time.js b/src/views/screen/components/screen-map-three/experience/utils/time.js new file mode 100644 index 0000000..680b19d --- /dev/null +++ b/src/views/screen/components/screen-map-three/experience/utils/time.js @@ -0,0 +1,25 @@ +import EventEmitter from "./eventEmitter"; +export default class Time extends EventEmitter { + constructor() { + super(); + this.start = Date.now(); + this.current = this.start; + this.elapsed = 0; + this.delta = 16; + window.requestAnimationFrame(() => { + this.tick(); + }); + } + + tick() { + const currentTime = Date.now(); + this.delta = currentTime - this.current; + this.current = currentTime; + this.elapsed = this.current - this.start; + this.trigger('tick'); + + window.requestAnimationFrame(() => { + this.tick(); + }); + } +} \ No newline at end of file diff --git a/src/views/screen/components/screen-map-three/experience/world/test.js b/src/views/screen/components/screen-map-three/experience/world/test.js new file mode 100644 index 0000000..599d3df --- /dev/null +++ b/src/views/screen/components/screen-map-three/experience/world/test.js @@ -0,0 +1,24 @@ +import * as THREE from 'three'; + +export default class Test { + constructor(experience) { + this.experience = experience; + this.scene = this.experience.scene; + + this.setGeometry(); + this.setMaterial(); + this.setMesh(); + } + setGeometry() { + this.geometry = new THREE.BoxGeometry(2,2,2); + } + setMaterial() { + this.geometryMaterial = new THREE.MeshStandardMaterial({ + color: '#db929d' + }); + } + setMesh() { + this.geometrytMesh = new THREE.Mesh(this.geometry, this.geometryMaterial); + this.scene.add(this.geometrytMesh); + } +} \ No newline at end of file diff --git a/src/views/screen/components/screen-map-three/experience/world/world.js b/src/views/screen/components/screen-map-three/experience/world/world.js new file mode 100644 index 0000000..3a2bbe0 --- /dev/null +++ b/src/views/screen/components/screen-map-three/experience/world/world.js @@ -0,0 +1,16 @@ +import EventEmitter from '../utils/eventEmitter'; + +import Test from "./test"; + +export default class World extends EventEmitter { + constructor(experience) { + super(); + this.experience = experience; + this.scene = this.experience.scene; + this.Test = new Test(this.experience); + } + + update() { + + } +} \ No newline at end of file diff --git a/src/views/screen/components/screen-map-three/index.vue b/src/views/screen/components/screen-map-three/index.vue index 9d6eedf..1d010f4 100644 --- a/src/views/screen/components/screen-map-three/index.vue +++ b/src/views/screen/components/screen-map-three/index.vue @@ -1,16 +1,16 @@ <template> - <div class="map-container" ref="mapContainer"> - + <div class="map-container" > + <canvas class="world" ref="worldContainer"></canvas> </div> </template> <script> -import World from './world/world'; +import Experience from './experience/index'; let world = null; export default { name: 'ScreenMapThree', mounted() { - world = new World(this.$refs.mapContainer); + world = new Experience(this.$refs.worldContainer); } } </script> @@ -19,5 +19,11 @@ .map-container { width: 100%; height: 100%; + position: absolute; + z-index: 0; + .world { + width: 100%; + height: 100%; + } } </style> \ No newline at end of file diff --git a/src/views/screen/components/screen-map-three/world/camera.js b/src/views/screen/components/screen-map-three/world/camera.js deleted file mode 100644 index 2605ae8..0000000 --- a/src/views/screen/components/screen-map-three/world/camera.js +++ /dev/null @@ -1,8 +0,0 @@ -import { PerspectiveCamera } from 'three'; - -function createCamera() { - const camera = new PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 100); - return camera; -} - -export { createCamera }; \ No newline at end of file diff --git a/src/views/screen/components/screen-map-three/world/renderer.js b/src/views/screen/components/screen-map-three/world/renderer.js deleted file mode 100644 index 3105c95..0000000 --- a/src/views/screen/components/screen-map-three/world/renderer.js +++ /dev/null @@ -1,11 +0,0 @@ -import {WebGLRenderer} from 'three'; - -function createRenderer() { - const renderer = new WebGLRenderer(); - renderer.setPixelRatio(Math.min(2,window.devicePixelRatio)); - renderer.setSize(window.innerWidth, window.innerHeight); - renderer.setClearAlpha(0); - return renderer; -} - -export {createRenderer}; \ No newline at end of file diff --git a/src/views/screen/components/screen-map-three/world/scene.js b/src/views/screen/components/screen-map-three/world/scene.js deleted file mode 100644 index 3c47871..0000000 --- a/src/views/screen/components/screen-map-three/world/scene.js +++ /dev/null @@ -1,9 +0,0 @@ -import {Scene} from 'three'; - -function createScene() { - const scene = new Scene(); - - return scene; -} - -export { createScene} \ No newline at end of file diff --git a/src/views/screen/components/screen-map-three/world/world.js b/src/views/screen/components/screen-map-three/world/world.js deleted file mode 100644 index aa1718b..0000000 --- a/src/views/screen/components/screen-map-three/world/world.js +++ /dev/null @@ -1,29 +0,0 @@ - -import { createScene } from "./scene"; -import { createRenderer } from "./renderer"; -import { createCamera } from "./camera"; -export default class World { - /** - * 鐢熸垚3d鍦烘櫙鏋勯�犲嚱鏁� - * @param {*} container 3d鍦烘櫙html瀹瑰櫒 - */ - constructor(container) { - this.container = container; - this.init(); - this.render(); - } - init() { - this.scene = createScene(); - this.renderer = createRenderer(); - this.camera = createCamera(); - this.scene.add(this.camera); - this.container.appendChild(this.renderer.domElement); - } - - render() { - this.renderer.render(this.scene, this.camera); - window.requestAnimationFrame(() => { - this.render(); - }) - } -} \ No newline at end of file diff --git a/src/views/screen/components/screen-wrapper/index.vue b/src/views/screen/components/screen-wrapper/index.vue index fdfd4cf..b9d9235 100644 --- a/src/views/screen/components/screen-wrapper/index.vue +++ b/src/views/screen/components/screen-wrapper/index.vue @@ -5,6 +5,7 @@ <el-button type="primary" @click="returnPath">绠$悊绯荤粺</el-button> </div> <div class="wrapper-content"> + <screen-map-three></screen-map-three> <div class="left-container wrapper"> <screen-face class="animate-enter-x enter-left"></screen-face> <screen-car class="animate-enter-x enter-left animate-delay-1"></screen-car> @@ -33,6 +34,8 @@ import ScreenMap from '../screen-map/index'; import ScreenMapCover from '../screen-map-cover/index'; import ScreenTable from '../screen-table/index'; +import ScreenMapThree from '../screen-map-three/index.vue'; + export default { name: 'ScreenWrapper', components: { @@ -43,7 +46,8 @@ ScreenCar, ScreenMap, ScreenTable, - ScreenMapCover + ScreenMapCover, + ScreenMapThree }, methods: { returnPath() { diff --git a/src/views/screen/index.vue b/src/views/screen/index.vue index 4e8c6fc..4e8cf80 100644 --- a/src/views/screen/index.vue +++ b/src/views/screen/index.vue @@ -1,9 +1,7 @@ <template> <div class="screen-container"> - <screen-title></screen-title> <v-scale-screen width="1920" height="1080" :autoScale="true" :delay="0" class="screen"> - <screen-map-three></screen-map-three> <screen-wrapper></screen-wrapper> </v-scale-screen> </div> @@ -13,7 +11,6 @@ <script> import ScreenTitle from './components/screen-title/index.vue'; import ScreenWrapper from './components/screen-wrapper/index.vue'; -import ScreenMapThree from './components/screen-map-three/index.vue'; export default { @@ -21,7 +18,6 @@ components: { ScreenTitle, ScreenWrapper, - ScreenMapThree }, data() { return { -- Gitblit v1.8.0