1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174 |
- <template>
- <div class="bigBox">
- <div class="left" v-show="isShow">
- <div class="leftOne">
- <div class="one">
- <lineChart v-if="flag" :speed="agentSpeed" :indexData="propsIndex" :propsName="propsName" :times="times" :stop="isAnimation" />
- </div>
- <div class="two">
- <lineChartTwo v-if="flag" :speed="targetSpeed" :indexData="propsIndex" :propsName="propsName" :times="times" :stop="isAnimation" />
- </div>
- <div class="three">
- <lineChartThree v-if="flag" :speed="propsDistance" :reportShow="reportShow" :times="times" :stop="isAnimation" />
- </div>
- </div>
- <div class="leftTwo">
- <div class="twoD" ref="twoD" v-if="flag">
- <lineChartFive v-if="flag" :propsData="propsCoordinates" :indexData="propsIndex" :propsName="propsName" :stop="isAnimation" />
- </div>
- <div class="four">
- <lineChartFour v-if="flag" :propsName="propsName" :direction="propsDirection" :indexData="propsIndex" :times="times" :stop="isAnimation" />
- <!-- <discChart
- v-if="flag"
- :propsData="1"
- /> -->
- </div>
- </div>
- </div>
- <div id="container" ref="box">
- <div class="infoTag" ref="infoTag"></div>
- <div class="SVShow" v-show="isShow">
- <!-- <div class="modelInfo">场景详细信息!!!!</div> -->
- <!-- <p class="modelInfo">{{ senceInfo }}</p> -->
- <p v-for="(item, index) in senceInfo" :key="index">{{ item }}</p>
- </div>
- <div class="tool">
- <button class="btn" style="width: 120px;" @click="goback">返 回 上 一 级</button>
- <el-select v-model="fileName" :disabled="selectDisabled" placeholder="请选择文件" @change="getFileContext">
- <el-option v-for="item in fileList" :key="item.value" :label="item.label" :value="item.value"> </el-option>
- </el-select>
- <el-select v-model="playSpeedData" @change="playSpeed">
- <el-option v-for="item in speedOptions" :key="item.value" :label="item.label" :value="item.value"> </el-option>
- </el-select>
- <el-select v-model="algoData" placeholder="请选择算法">
- <el-option v-for="item in algoOptions" :key="item.value" :label="item.label" :value="item.value"> </el-option>
- </el-select>
- <button class="btn" @click="Suspend">暂 停</button>
- <button class="btn" @click="Begin">开 始</button>
- <button class="btn" @click="playBack" :disabled="!isShow">回 放</button>
- <input type="file" ref="fileInput" style="display: none" @change="importData" accept=".json" />
- </div>
- <div class="small" id="small" ref="small" v-show="isShow"></div>
- </div>
- <div class="right">
- <div class="textShow" v-show="isShow">
- <div class="textShowBox">
- <p v-for="(item, index) in eventText" :key="index">{{ item }}</p>
- <div class="report" v-show="reportShow">
- <p style="color: black" v-for="(item, index) in reportInfo" :key="index">
- {{ item }}
- </p>
- </div>
- </div>
- </div>
- </div>
- </div>
- </template>
- <script>
- import * as THREE from 'three'
- import TWEEN from '@tweenjs/tween.js'
- // 引入轨道控制器
- import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
- // import { BufferGeometryUtils } from 'three';
- // import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
- import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js'
- import lineChart from '@/views/3dDemo/lineChart'
- import lineChartTwo from '@/views/3dDemo/lineChartTwo'
- import lineChartThree from '@/views/3dDemo/lineChartThree'
- import lineChartFour from '@/views/3dDemo/lineChartFour'
- import lineChartFive from '@/views/3dDemo/lineChartFive'
- // import discChart from "@/views/3dDemo/discChart";
- import '@/assets/css/global.css'
- let light
- let scene = null
- let sceneSmall = null
- let camera = null
- const SHADOW_MAP_WIDTH = 2048,
- SHADOW_MAP_HEIGHT = 1024
- let containerWidth, containerHeight
- const raycaster = new THREE.Raycaster()
- const mouse = new THREE.Vector2()
- export default {
- name: 'threeDemo',
- components: {
- lineChart,
- lineChartTwo,
- lineChartThree,
- lineChartFour,
- lineChartFive
- // discChart
- },
- data() {
- return {
- jsonData: null,
- // 场景
- // scene: null,
- // sceneSmall: null,
- // 渲染器
- renderer: null,
- smallRenderer: null,
- // 摄像机
- // camera: null,
- OrbitControl: null,
- // 物体形状
- geometry: null,
- // 物体材质
- material: [],
- // 坐标轴
- axes: null,
- // container
- container: null,
- // 网格模型
- mesh: null,
- // 模型
- models: [],
- // 时间和事件
- allTimes: [],
- // 所有事件
- allEvents: [],
- eventText: [],
- // 改变的距离
- distance: [],
- // 所有距离
- allDistance: [],
- particleSystem: null,
- // 倍速
- playSpeedData: 1,
- speedOptions: [
- { value: 1, label: '1倍速' },
- { value: 4, label: '4倍速' },
- { value: 8, label: '8倍速' },
- { value: 16, label: '16倍速' },
- { value: 32, label: '32倍速' },
- { value: 64, label: '64倍速' },
- { value: 128, label: '128倍速' }
- ],
- // 暂停和开始
- isAnimation: false,
- animationId: null,
- waveAnimateId: null,
- // 保存动画值
- animationValues: {},
- waveImg: require('../../assets/界面.jpg'),
- // 保存导入的文件
- file: null,
- fileList: [],
- fileName: null,
- isFile: false,
- isShow: false,
- flag: false,
- // props的值
- agentSpeed: [],
- targetSpeed: [],
- times: [],
- propsDistance: [],
- mixer: null,
- propsDirection: [],
- propsName: [],
- propsIndex: null,
- propsCoordinates: [],
- // 场景信息
- senceInfo: '',
- // 评估报告展示
- reportShow: false,
- reportInfo: null,
- selectDisabled: false,
- tagArray: [],
- waweShow: false,
- tween: null,
- tween1: null,
- tweenTargetPosition: null,
- maxNum: null,
- // 选择算法
- algoData: '',
- // 算法选项
- algoOptions: [
- {
- value: '选项1',
- label: '算法1'
- },
- {
- value: '选项2',
- label: '算法2'
- },
- {
- value: '选项3',
- label: '算法3'
- }
- ]
- }
- },
- mounted() {
- this.getFile()
- this.fileName=this.$route.params.fileName
- this.getFileContext()
- this.initContainer()
- this.initSmall()
- this.initOrbitControls()
- // this.createCube();
- this.createWave()
- this.waveModel()
- },
- beforeDestroy() {
- window.removeEventListener('mousemove', this.onMouseMove);
- this.clearSence()
- cancelAnimationFrame(this.animationId);
-
- },
- methods: {
- getFile() {
- this.$axios.get(`/api/`).then((res) => {
- console.log('res', res)
- if (res.status === 200) {
- if (res.data.length === 0) {
- this.$message.error('文件夹下暂无数据,请添加数据')
- }
- res.data.forEach((item, index) => {
- this.fileList.push({
- label: item,
- value: item
- })
- })
- } else {
- this.$message.warning('读文件列表有误')
- }
- })
- containerWidth = document.getElementById('container').clientWidth
- containerHeight = document.getElementById('container').clientHeight
- },
- goback(){
- window.removeEventListener('mousemove', this.onMouseMove);
- this.isAnimation = false
- cancelAnimationFrame(this.animationId);
- this.renderer.dispose();
- this.renderer.forceContextLoss();
- this.renderer.content = null;
- this.renderer = null;
- this.clearSence()
- this.$router.push({ name:'simulationSystem'})
- },
- // 初始化场景
- initContainer() {
- let container = this.$refs.box
- this.container = container
- // 创建场景
- scene = new THREE.Scene()
- // 创建相机、相机位置、设置相机方向(指向的场景对象)
- camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 1, 20000)
- camera.position.set(1000, 0, 1000)
- camera.lookAt(scene.position)
- // this.camera.lookAt(0, 0, 0)
- //创建渲染器
- this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true })
- // this.renderer.setClearAlpha(0.1);
- // this.renderer.setClearColor(0x000000,0)
- this.renderer.setSize(container.clientWidth, container.clientHeight)
- // 将渲染器添加到页面
- container.appendChild(this.renderer.domElement)
- // 环境光
- var ambienLight = new THREE.AmbientLight(0xcccccc, 0.5)
- scene.add(ambienLight)
- light = new THREE.DirectionalLight(0xffffff, 3)
- light.position.set(0, 1500, 1000)
- light.castShadow = true
- light.shadow.camera.top = 2000
- light.shadow.camera.bottom = -2000
- light.shadow.camera.left = -2000
- light.shadow.camera.right = 2000
- light.shadow.camera.near = 1200
- light.shadow.camera.far = 2500
- light.shadow.bias = 0.0001
- light.shadow.mapSize.width = SHADOW_MAP_WIDTH
- light.shadow.mapSize.height = SHADOW_MAP_HEIGHT
- scene.add(light)
- // this.axes = new THREE.AxesHelper(500)
- // this.scene.add(this.axes)
- },
- // 初始化小窗口
- initSmall() {
- let small = this.$refs.small
- sceneSmall = new THREE.Scene()
- const geometry = new THREE.CircleGeometry()
- const material = new THREE.MeshStandardMaterial({})
- const mesh = new THREE.Mesh(geometry, material)
- sceneSmall.add(mesh)
- //创建渲染器
- this.smallRenderer = new THREE.WebGLRenderer()
- small.appendChild(this.smallRenderer.domElement)
- this.axes = new THREE.AxesHelper(2500)
- sceneSmall.background = new THREE.Color('#000')
- sceneSmall.add(this.axes)
- },
- // 初始化控制器
- initOrbitControls() {
- // 创建轨道控制器 相机围绕模型看到的角度
- this.OrbitControl = new OrbitControls(camera, this.renderer.domElement)
- // 设置轨道自然
- this.OrbitControl.enableDamping = true
- this.OrbitControl.enableRotate = false //禁止旋转
- this.OrbitControl.keys = {
- LEFT: 'ArrowLeft', // left arrow
- UP: 'ArrowUp', // up arrow
- RIGHT: 'ArrowRight', // right arrow
- BOTTOM: 'ArrowBottom' // down arrow
- }
- // 设置惯性
- this.OrbitControl.update()
- this.addEvent(window, 'keydown', this.onKeyDown)
- },
- onKeyDown(e) {
- // const camera = camera
- const controls = this.OrbitControl
- if (!camera || !controls) {
- return
- }
- const sensitivity = 3 // you may want to put it into settings
- const p = new THREE.Vector3() // camera's position
- camera.getWorldPosition(p)
- const t = controls.target // target point
- const newTarget = t.clone()
- if (e.code === 'ArrowLeft' || e.code === 'ArrowRight') {
- const ANGLE = sensitivity
- let theta = (Math.PI * ANGLE) / 180
- if (e.code === 'ArrowLeft') {
- theta = -theta
- }
- const newPos = new THREE.Vector3()
- newPos.x = p.x * Math.cos(theta) - p.z * Math.sin(theta)
- newPos.z = p.z * Math.cos(theta) + p.x * Math.sin(theta)
- camera.position.set(newPos.x, p.y, newPos.z)
- controls.target = newTarget
- controls.update()
- } else if (e.code === 'ArrowUp' || e.code === 'ArrowDown') {
- const ANGLE2 = sensitivity
- let theta2 = (Math.PI * ANGLE2) / 180
- const distVec = new THREE.Vector3(t.x - p.x, t.y - p.y, t.z - p.z)
- const dist = distVec.length()
- const deltaY = t.y - p.y
- if (e.code === 'ArrowDown') {
- theta2 = -theta2
- }
- const angle = Math.asin(deltaY / dist) + theta2
- if (angle < -Math.PI / 2 || angle > Math.PI / 2) {
- return // cannot rotate that much
- }
- const newDeltaY = Math.sin(angle) * dist
- newTarget.y = t.y + (newDeltaY - deltaY)
- controls.target = newTarget
- controls.update()
- }
- },
- addEvent(target, type, handler) {
- target.addEventListener(type, handler)
- },
- // 创建立方体
- createCube() {
- const size = this.maxNum * 2
- this.geometry = new THREE.BoxGeometry(size, size, size)
- // this.geometry = new THREE.SphereGeometry(500, 60, 40);
- this.geometry.scale(1, 1, 1)
- // 创建矩形网格
- this.mesh = new THREE.Mesh(this.geometry, this.material)
- this.mesh.geometry.scale(1, 1, 1)
- scene.add(this.mesh) //网格模型添加到场景中
- },
- // 动画
- animate(modelInfo) {
- console.log("222");
- if (this.isAnimation) {
- setTimeout(() => {
- this.animationId = requestAnimationFrame(() => this.animate(modelInfo))
- this.modelMove(modelInfo)
- // 渲染场景
- this.tween?.update()
- // this.tween1?.update();
- this.renderer?.render(scene, camera)
- this.smallRenderer.render(sceneSmall, camera)
- }, 150)
- }
- },
- // 创建扩散波
- createWave() {
- // var textureLoader = new THREE.TextureLoader();
- // 底部半径、顶部半径、高度和面的数量
- const geometry = new THREE.CylinderGeometry(150, 150, 10, 500)
- const geometry2 = new THREE.CylinderGeometry(200, 200, 10, 500)
- const material = new THREE.MeshBasicMaterial({
- color: 0x0078d4,
- side: THREE.DoubleSide,
- transparent: true
- // map: textureLoader.load(this.waveImg),
- })
- const circle = new THREE.Mesh(geometry, [material]) //用数组只贴边面
- const circle2 = new THREE.Mesh(geometry2, [material]) //用数组只贴边面
- circle.name = 'circle'
- circle2.name = 'circle2'
- circle.position.set(-1000, 1000, -1000)
- circle2.position.set(-1000, 1000, -1000)
- scene.add(circle)
- scene.add(circle2)
- let s = 0,
- p = 0
- const scaleFactor = 3 // 调整这个值以控制波纹的扩大速度
- const render1 = () => {
- if (s > 160) {
- s = 0
- p = 160
- }
- circle.scale.set(1 + (s / 60) * scaleFactor, 1, 1 + (s / 60) * scaleFactor)
- circle2.scale.set(1 + (s / 60) * scaleFactor, 1, 1 + (s / 60) * scaleFactor)
- circle.material[0].opacity = p / 160
- circle2.material[0].opacity = p / 160
- s++
- p--
- this.waveAnimateId = requestAnimationFrame(render1)
- }
- render1()
- },
- // 引入发射扩散波模型
- waveModel() {
- const objLoader = new OBJLoader()
- const material = new THREE.MeshStandardMaterial({ color: 0xfbc31d })
- objLoader.load('/models/obj.obj', (model) => {
- model.scale.set(0.03, 0.03, 0.03)
- model.name = 'waveModel'
- model.traverse(function (child) {
- if (child instanceof THREE.Mesh) {
- child.material = material // 设置模型的材质
- // child.name='waveModel'
- }
- })
- model.position.set(-1000, 1000, -1000)
- scene.add(model)
- })
- },
- // 模型加载
- createRole(data, callback) {
- const [index, modelInfo] = data
- const material = new THREE.MeshStandardMaterial({
- color: modelInfo.color
- })
- const objLoader = new OBJLoader()
- objLoader.load(
- this.models[index].path,
- (model) => {
- const size = this.models[index].scale
- model.scale.set(size, size, size)
- model.position.copy(this.models[index].route[0])
- model.traverse(function (child) {
- if (child instanceof THREE.Mesh) {
- child.material = material // 设置模型的材质
- }
- })
- this.models[index].model = model
- scene.add(model)
- // 在模型加载成功后执行回调
- if (typeof callback === 'function') {
- callback(model)
- }
- },
- undefined,
- (error) => {
- console.error(error)
- }
- )
- },
- // 控制模型运动
- modelMove(modelInfo) {
- if (modelInfo.pathIndex === modelInfo.route.length && this.eventText.length === this.allEvents.length) {
- this.reportShow = true
- return
- }
- if (this.playSpeedData <= modelInfo.route.length - modelInfo.pathIndex) {
- let index = modelInfo.pathIndex
- const currentPoint = modelInfo.route[index]
- if (modelInfo.route.length - modelInfo.pathIndex > 1) {
- const nextPoint = modelInfo.route[index + this.playSpeedData]
- const direction = new THREE.Vector3().subVectors(nextPoint, currentPoint).normalize()
- // 计算模型当前位置向下一个位置的方向向量来确定模型的朝向
- modelInfo.model.lookAt(modelInfo.model.position.clone().add(direction))
- modelInfo.movedRoute.push(modelInfo.model?.position.clone())
- modelInfo.model.position.copy(modelInfo.route[index])
- // 调用生成轨迹函数
- this.makeCurve(modelInfo)
- }
- if (modelInfo.name === 'agent' || modelInfo.name === 'agent1') {
- // this.agentSpeed.push(modelInfo.speed[index]);
- // this.times.push(this.allTimes[index]);
- this.times.push(...this.allTimes.slice(modelInfo.prevIndex, index))
- // this.propsDistance.push(...this.distance.slice(modelInfo.prevIndex,index));
- this.propsIndex = index
- // 展示生成事件文字
- this.showText(this.allTimes[index])
- }
- if (modelInfo.name.startsWith('agent')) {
- this.agentSpeed[modelInfo.name]?.push(...modelInfo.speed.slice(modelInfo.prevIndex, index))
- // this.propsDistance.push(...this.distance.slice(modelInfo.prevIndex,index));
- // 距离
- this.showDistance(this.allTimes[index], modelInfo.name)
- if (this.allDistance[modelInfo.name][index] <= 3) {
- // && !this.waweShow
- for (let i = scene.children.length - 1; i >= 0; i--) {
- const child = scene.children[i]
- if (child.name === 'circle2' || child.name === 'circle' || child.name === 'waveModel') {
- scene.remove(child)
- child.children.forEach((child) => {
- child.remove(child)
- if (child instanceof THREE.Mesh) {
- child.geometry.dispose()
- child.material.dispose()
- }
- })
- // cancelAnimationFrame(this.waveAnimateId);
- // this.waveAnimateId = null;
- }
- }
- // this.waweShow = true;
- let position = {
- x: modelInfo.route[index].x - 30,
- y: modelInfo.route[index].y + 30,
- z: modelInfo.route[index].z - 30
- }
- this.tween = new TWEEN.Tween(camera.position)
- .to(position, 2000)
- .onUpdate(() => {
- camera.lookAt(this.tweenTargetPosition.x, this.tweenTargetPosition.y, this.tweenTargetPosition.z)
- this.OrbitControl.target = new THREE.Vector3(this.tweenTargetPosition.x, this.tweenTargetPosition.y, this.tweenTargetPosition.z)
- })
- .start()
- }
- }
- this.propsDirection[modelInfo.name]?.push(...modelInfo.direction.slice(modelInfo.prevIndex, index))
- if (modelInfo.name === 'target') {
- // this.targetSpeed.push(modelInfo.speed[index]);
- this.targetSpeed.push(...modelInfo.speed.slice(modelInfo.prevIndex, index))
- this.tweenTargetPosition = {
- x: modelInfo.route[index].x,
- y: modelInfo.route[index].y,
- z: modelInfo.route[index].z
- }
- }
- modelInfo.prevIndex = index
- modelInfo.pathIndex += this.playSpeedData
- } else {
- this.playSpeedData = 1
- }
- },
- makeCurve(modelInfo) {
- const particleGeometry = new THREE.BufferGeometry()
- const particleMaterial = new THREE.PointsMaterial({
- color: modelInfo.curveColor,
- size: 3
- })
- const routePoint = modelInfo.route.length
- if (modelInfo.movedRoute.length >= 2) {
- const curve = new THREE.CatmullRomCurve3(modelInfo.movedRoute)
- curve.curveType = 'catmullrom'
- curve.closed = false
- curve.tension = 0.5
- const points = curve.getPoints(routePoint) // 获取曲线上的n个点
- particleGeometry.setFromPoints(points)
- this.particleSystem = new THREE.Points(particleGeometry, particleMaterial)
- if (modelInfo.name.startsWith('agent')) {
- this.particleSystem.userData.distance = this.allDistance[modelInfo.name][modelInfo.pathIndex]
- this.particleSystem.userData.time = this.allTimes[modelInfo.pathIndex]
- this.particleSystem.userData.name = modelInfo.name
- }
- scene.add(this.particleSystem)
- this.tagArray.push(this.particleSystem)
- } else {
- // console.error('Not enough points to create curve.')
- return
- }
- },
- onMouseMove(event) {
- const infoTag = this.$refs.infoTag
- mouse.x = (event.layerX / containerWidth) * 2 - 1
- mouse.y = -(event.layerY / containerHeight) * 2 + 1
- raycaster.setFromCamera(mouse, camera)
- var intersects = raycaster.intersectObjects(this.tagArray)
- if (intersects.length === 0) {
- infoTag.style.display = 'none'
- return
- } //有相交物体时
- if (intersects.length > 0) {
- let object = intersects[0].object
- if (object.userData.name?.startsWith('agent')) {
- infoTag.innerHTML = `名称:雷${object.userData.name.substr(-1)}
- <br>时间:${object.userData.time}
- <br>距离:${object.userData.distance}km`
- infoTag.style.display = 'block'
- infoTag.style.cursor = 'pointer'
- infoTag.style.left = event.layerX + 10 + 'px' //一定要拼接 px
- infoTag.style.top = event.layerY + 10 + 'px'
- } else {
- return
- }
- }
- },
- getFileContext() {
- if(!this.fileName){
- this.$message.warning('请手动选择回放的数据')
- return
- }
- const data = { fileName: this.fileName }
- this.$axios.post('/api/fileContent', data).then((res) => {
- // console.log("11",res);
- if (res.status === 200 && res.data.code === 200) {
- this.jsonData = res.data.data
- this.handelData(this.jsonData)
- this.selectDisabled = true
- } else {
- this.$message.warning('文件读取内容失败')
- }
- })
- // this.$axios.get('/api/readTxt').then((res)=>{
- // console.log("11",res);
- // })
- },
- // 触发文件上传输入框的点击事件
- importBtn() {
- this.$refs.fileInput.click()
- },
- // 导入数据
- importData(event) {
- // importData(file) {
- const file = event?.target.files[0] // 获取上传的文件
- // console.log("导入",file);
- if (file) {
- const reader = new FileReader() // 创建一个文件阅读器对象
- reader.onload = (e) => {
- try {
- const content = e.target.result // 获取文件内容
- const jsonContent = JSON.parse(content) // 解析 JSON
- this.jsonData = jsonContent // 将 JSON 数据存储在组件的数据中
- this.jsonData = jsonContent.filter((item, index) => index % 3 === 0 || item[1].events.length !== 0)
- this.handelData(this.jsonData)
- } catch (error) {
- console.error('Error reading the file:', error)
- }
- }
- reader.readAsText(file) // 以文本形式读取文件内容
- }
- },
- handelData(rawData1) {
- const rawData = rawData1.filter((item, index) => {
- return index % 10 === 0 || item[1].events.length !== 0 || item[1].report
- })
- // console.log('rawData', rawData)
- const color = [0xc1232b, 0x5470c6, 0xfac858, 0xee6666]
- this.models = []
- this.allTimes = []
- this.allEvents = []
- this.direction = []
- this.distance = []
- let beginCoordinate = null
- let maxData = 0
- const agents = {}
- const target = {
- path: '/models/qianting.obj',
- name: 'target',
- route: [],
- pathIndex: 0,
- model: null,
- scale: 15,
- isMoving: false,
- movedRoute: [],
- color: 0x3cf44b,
- curveColor: 0x3cf44b,
- speed: [],
- direction: [],
- nowSpeed: null,
- coordinate: [],
- prevIndex: 0
- }
- this.senceInfo = rawData[0][1].info
- rawData.forEach((data) => {
- if (data[1].events.length !== 0) {
- this.allEvents.push({
- time: data[0],
- event: data[1].events
- })
- }
- if (data[1].report) {
- this.reportInfo = data[1].report
- }
- this.allTimes.push(data[0])
- Object.keys(data[1].distance).forEach((key, index) => {
- const dis = Number(parseFloat(data[1].distance[key]).toFixed(2))
- if (!this.distance[key]) {
- this.distance[key] = [[parseFloat(data[0]), dis]]
- this.allDistance[key] = []
- }
- this.allDistance[key].push(dis)
- if (this.distance[key][this.distance[key].length - 1][1] !== dis) {
- this.distance[key].push([parseFloat(data[0]), dis])
- }
- if (!this.propsDistance[key]) {
- this.propsDistance[key] = []
- this.propsDistance[key].push(this.distance[key][0])
- }
- })
- // 处理代理数据
- Object.keys(data[1]).forEach((key, index) => {
- if (key.startsWith('agent')) {
- if (!agents[key]) {
- agents[key] = {
- path: '/models/yulei2.obj',
- name: key,
- route: [],
- pathIndex: 0,
- model: null,
- scale: 15,
- isMoving: false,
- movedRoute: [],
- color: 0xe6194b,
- curveColor: color[index],
- speed: [],
- direction: [],
- nowSpeed: null,
- coordinate: [],
- prevIndex: 0
- }
- }
- if (!beginCoordinate) {
- beginCoordinate = [data[1][key].agent_center_x, data[1][key].agent_center_y]
- }
- agents[key].route.push(new THREE.Vector3(data[1][key].agent_center_x / 2, 100, data[1][key].agent_center_y / 2))
- agents[key].speed.push(parseInt(data[1][key].agent_speed))
- agents[key].direction.push(
- data[1][key].agent_direction > 180 ? -(360 - parseInt(data[1][key].agent_direction)) : parseInt(data[1][key].agent_direction)
- )
- agents[key].coordinate.push([data[1][key].agent_center_x - beginCoordinate[0], data[1][key].agent_center_y - beginCoordinate[1]])
- maxData = Math.max(data[1][key].agent_center_x, data[1][key].agent_center_y, maxData)
- }
- })
- // 处理目标数据
- const targetX = data[1].target.target_center_x
- const targetY = data[1].target.target_center_y
- target.route.push(new THREE.Vector3(targetX / 2, 100, targetY / 2))
- target.speed.push(parseInt(data[1].target.target_speed))
- target.direction.push(
- data[1].target.target_direction > 180 ? -(360 - parseInt(data[1].target.target_direction)) : parseInt(data[1].target.target_direction)
- )
- target.coordinate.push([targetX - beginCoordinate[0], targetY - beginCoordinate[1]])
- maxData = Math.max(targetX, targetY, maxData)
- })
- this.maxNum = Math.ceil(maxData)
- this.models = [].concat(...[Object.values(agents), target])
- // console.log("this.models", this.models);
- // console.log("this.distance",this.distance);
- // console.log("this.allDistance",this.allDistance);
- this.models.forEach((modelInfo, index) => {
- // this.propsDirection.push(modelInfo.direction);
- this.propsDirection[modelInfo.name] = []
- this.propsName.push(modelInfo.name)
- this.propsCoordinates[modelInfo.name] = modelInfo.coordinate
- if (modelInfo.name.startsWith('agent')) {
- this.agentSpeed[modelInfo.name] = []
- }
- this.createRole([index, modelInfo], () => {
- this.isAnimation = true
- this.animate(modelInfo)
- this.isFile = true
- })
- })
- this.isShow = true
- this.flag = true
- this.createCube()
- window.addEventListener('mousemove', this.onMouseMove)
- },
- // 倍速播放
- playSpeed() {
- this.playSpeedData = parseInt(this.playSpeedData)
- },
- // 暂停按钮
- Suspend() {
- this.isAnimation = false
- },
- // 开始按钮
- Begin() {
- if (!this.isAnimation) {
- this.isAnimation = true
- this.models.forEach((modelInfo) => {
- this.animate(modelInfo) // 重新开始动画循环
- })
- }
- },
- showDistance(time, name) {
- const filterData = this.distance[name]?.filter((item) => item[0] <= parseFloat(time))
- if (filterData?.length !== this.propsDistance[name]?.length) {
- this.propsDistance[name] = filterData
- }
- //console.log('propsDistance', this.propsDistance)
- // if(this.distance[name].some(item => item[0] === parseFloat(time)) && !(this.propsDistance[name].some(item => item[0] === parseFloat(time)))){
- // this.propsDistance[name].push(this.distance[name].find(item => item[0] === parseFloat(time)));
- // console.log("this.propsDistance",this.propsDistance);
- // }
- },
- // 显示文本解释
- showText(index) {
- // allEvent 所有有事件的时间事件集合
- this.allEvents?.forEach((item) => {
- if (parseFloat(index) >= parseFloat(item.time)) {
- if (!this.eventText?.includes(item.event)) {
- this.eventText.push(item.event)
- }
- }
- })
- },
- // 回放!!!!
- playBack() {
- // this.clearSence()
- this.Suspend()
- this.clearSence()
- this.flag = false
- if (this.waweShow) {
- this.createWave()
- this.waweShow = false
- }
- setTimeout(() => {
- this.clearSence()
- cancelAnimationFrame(this.animationId)
- this.animationId = null
- this.waveModel()
- this.handelData(this.jsonData)
- }, 100)
- },
- // 清除场景中的信息
- clearSence() {
- for (let i = scene.children.length - 1; i >= 0; i--) {
- const child = scene.children[i]
- if (child instanceof THREE.Group) {
- scene.remove(child)
- child.children.forEach((child) => {
- child.remove(child)
- // 如果子对象是 Mesh,则需要手动释放几何体和材质
- if (child instanceof THREE.Mesh) {
- child.geometry.dispose()
- child.material.dispose()
- }
- })
- }
- if (child instanceof THREE.Points) {
- scene.remove(child)
- if (child && child.geometry) {
- child.geometry.dispose()
- } else if (child && child.material) {
- child.material.dispose()
- } else {
- console.log('未找到数据')
- }
- }
- if (child === this.particleSystem) {
- scene.remove(child)
- if (child.geometry) {
- child.geometry.dispose()
- }
- if (child.material) {
- child.material.dispose()
- }
- // 可以在这里将 this.particleSystem 设为 null,以防止后续误用
- this.particleSystem = null
- }
- //清除数据
- this.models = []
- this.allTimes = []
- this.allEvents = []
- this.distance = []
- this.direction = []
- this.eventText = []
- this.agentSpeed = []
- this.targetSpeed = []
- this.times = []
- this.propsDistance = []
- this.propsDirection = []
- }
- }
- }
- }
- </script>
- <style scoped>
- /* *{
- padding: 0;
- margin: 0;
- box-sizing:content-box
- } */
- .bigBox {
- width: 100%;
- height: 100%;
- /* width: 5760px;
- height: 1080px; */
- display: flex;
- position: relative;
- }
- #container {
- width: 1920px;
- height: 1080px;
- position: absolute;
- left: 1920px;
- top: 0;
- }
- .infoTag {
- display: none;
- position: absolute;
- top: 0;
- left: 0;
- background-color: #fff;
- border: 1px solid #ccc;
- padding: 5px;
- /* margin: 4px; */
- }
- .right {
- width: 1800px;
- height: 1080px;
- position: absolute;
- right: 0;
- top: 0;
- }
- .left {
- width: 1920px;
- height: 1080px;
- display: flex;
- flex-direction: row;
- }
- .leftOne {
- width: 900px;
- height: 1080px;
- position: absolute;
- top: 0;
- left: 50px;
- display: flex;
- flex-direction: column;
- justify-content: space-around;
- }
- .leftTwo {
- width: 800px;
- height: 1080px;
- position: absolute;
- top: 0;
- left: 1050px;
- display: flex;
- flex-direction: column;
- justify-content: space-around;
- }
- .one {
- background: url('../../assets/鱼雷速度.png') center no-repeat;
- }
- .two {
- background: url('../../assets/目标速度.jpg') center no-repeat;
- }
- .three {
- background: url('../../assets/雷目距离.jpg') center no-repeat;
- /* background: url("../../assets/目标速度.jpg") center no-repeat; */
- }
- .one,
- .two,
- .three {
- width: 900px;
- height: 300px;
- background-size: 900px 300px;
- position: relative;
- /* top: 50%; */
- /* margin: 1.875rem 1.25rem 0.9375rem 0.9375rem; */
- }
- .four {
- background: url('../../assets/航向角.jpg') center no-repeat;
- }
- /* .two,
- .four {
- left: 700px;
- } */
- .four {
- width: 900px;
- height: 300px;
- background-size: 900px 300px;
- position: relative;
- margin: 25px 0 0 -50px;
- }
- .twoD {
- background: url('../../assets/右框.jpg') center no-repeat;
- }
- .twoD {
- width: 850px;
- height: 650px;
- background-size: 850px 650px;
- margin-top: 25px;
- margin-left: -20px;
- z-index: 9999;
- }
- .SVShow {
- background: url('../../assets/右框.jpg') center no-repeat;
- }
- .SVShow {
- width: 430px;
- height: 300px;
- background-size: 430px 300px;
- display: flex;
- align-items: center;
- flex-direction: column;
- position: absolute;
- z-index: 9999;
- top: 8%;
- }
- .SVShow >>> p {
- width: 380px;
- color: white;
- font-size: 1.6rem;
- /* margin-left: 30px; */
- margin: 0;
- padding: 10px;
- overflow: hidden;
- }
- .modelInfo {
- /* height: 50px;
- line-height: 50px; */
- margin: 20px;
- color: white;
- font-size: 1.75rem;
- }
- .report {
- width: 1630px;
- background-color: white;
- margin: 30px;
- padding-top: 15px;
- font-family: Simsun;
- }
- .tool {
- width: 1100px;
- height: 80px;
- line-height: 80px;
- position: absolute;
- bottom: 0;
- font-size: 16px;
- margin: 20px;
- }
- .btn {
- width: 80px;
- height: 40px;
- background-color: #01192a;
- /* background: url("../../assets/界面.jpg") center no-repeat;
- background-size: 80px 40px; */
- color: #02d1fd;
- font-weight: 700;
- box-shadow: inset 0 0 7px 3px #215c76;
- margin: 0 15px;
- /* inset 表示内阴影 */
- }
- .textShow {
- background: url('../../assets/右框.jpg') center no-repeat;
- }
- .textShow {
- width: 1700px;
- height: 1000px;
- background-size: 1700px 1000px;
- /* opacity: 0.4; */
- position: absolute;
- z-index: 9999;
- top: 40px;
- overflow: hidden;
- }
- .textShowBox {
- width: 1800px;
- height: 950px;
- overflow: hidden;
- overflow-y: scroll;
- margin-top: 25px;
- }
- .textShow >>> p {
- width: 1600px;
- color: white;
- font-size: 2.125rem;
- padding: 0px 30px;
- /* margin-left: 30px; */
- overflow: hidden;
- }
- .small {
- width: 9.375rem;
- height: 9.375rem;
- overflow: hidden;
- border: 1px solid gray;
- border-radius: 50%;
- position: absolute;
- background-color: rgb(17, 17, 17);
- bottom: 3.125rem;
- right: 0;
- }
- .small >>> canvas {
- transform: translateX(-73px);
- }
- ::v-deep .el-select {
- width: 150px;
- margin: 0 20px;
- }
- ::v-deep .el-input__inner {
- background-color: transparent;
- color: white;
- }
- ::v-deep .el-select-dropdown__item {
- color: #fff;
- }
- ::v-deep .el-scrollbar,
- ::v-deep .el-select-dropdown {
- background-color: transparent !important;
- color: #fff !important;
- }
- ::v-deep .el-scrollbar__wrap,
- ::v-deep .el-select-dropdown__list {
- background-color: #0b1a37;
- color: #fff !important;
- }
- ::v-deep .el-select-dropdown__item.hover,
- .el-select-dropdown__item:hover {
- background-color: rgba(0, 0, 0, 0.3);
- color: #fff;
- }
- ::v-deep .el-select .el-input.is-disabled .el-input__inner {
- background-color: transparent;
- }
- </style>
|