修改点云和地图
This commit is contained in:
@@ -14,6 +14,7 @@ import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
|
||||
import { mapGetters } from 'vuex'
|
||||
// import { points } from '../../config/point.js'
|
||||
// import { points1 } from '../../config/point1.js'
|
||||
// import { points2 } from '../../config/point2.js'
|
||||
export default {
|
||||
/* eslint-disable */
|
||||
data () {
|
||||
@@ -361,6 +362,10 @@ export default {
|
||||
// const arr = points1.data
|
||||
// this.updatePointCloud(arr);
|
||||
// }, 5000)
|
||||
// setTimeout(() => {
|
||||
// const arr = points2.data
|
||||
// this.updatePointCloud(arr);
|
||||
// }, 10000)
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -561,5 +566,4 @@ export default {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
../../config/point copy.js
|
||||
</style>
|
||||
@@ -14,11 +14,19 @@
|
||||
@mouseup="handleMouseUp"
|
||||
@mouseleave="handleMouseUp"
|
||||
></canvas>
|
||||
<!-- <el-row type="flex" justify="end" class="map_tools">
|
||||
<el-button type="primary" :disabled="zoomPercentage === 2" icon="el-icon-minus" size="mini" style="border: 0;border-radius: 0;" @click="zoomOut"></el-button>
|
||||
<el-row type="flex" justify="end" class="map_tools">
|
||||
<el-button
|
||||
type="primary"
|
||||
:disabled="!carPosition?.x || !carPosition?.y"
|
||||
icon="el-icon-location"
|
||||
size="mini"
|
||||
style="border-left: 0;border-top: 0;border-bottom: 0;border-radius: 0;"
|
||||
@click="centerToCar"
|
||||
></el-button>
|
||||
<el-button type="primary" :disabled="zoomPercentage === 2" icon="el-icon-minus" size="mini" style="border: 0;border-radius: 0;margin-left: 0" @click="zoomOut"></el-button>
|
||||
<div class="zoom_data">{{ zoomPercentage }}%</div>
|
||||
<el-button type="primary" :disabled="zoomPercentage === 200" icon="el-icon-plus" size="mini" style="border: 0;border-radius: 0;" @click="zoomIn"></el-button>
|
||||
</el-row> -->
|
||||
</el-row>
|
||||
</div>
|
||||
<div
|
||||
v-if="showPopup"
|
||||
@@ -120,13 +128,31 @@ export default {
|
||||
mounted () {
|
||||
this.preloadMarkerImage()
|
||||
this.preloadCarImage()
|
||||
this.loadAllDataInParallel()
|
||||
this.loadAllDataInParallel().then(() => {
|
||||
this.waitForResourcesReady().then(() => {
|
||||
this.centerToCar();
|
||||
});
|
||||
});
|
||||
document.addEventListener('click', this.handleDocumentClick)
|
||||
},
|
||||
beforeDestroy () {
|
||||
document.removeEventListener('click', this.handleDocumentClick)
|
||||
},
|
||||
methods: {
|
||||
waitForResourcesReady() {
|
||||
return new Promise((resolve) => {
|
||||
const checkReady = () => {
|
||||
const isImagesReady = this.imageLoadStatus.map && this.imageLoadStatus.marker && this.imageLoadStatus.car;
|
||||
const isCanvasReady = this.canvas && this.ctx;
|
||||
if (isImagesReady && isCanvasReady) {
|
||||
resolve();
|
||||
} else {
|
||||
setTimeout(checkReady, 100);
|
||||
}
|
||||
};
|
||||
checkReady();
|
||||
});
|
||||
},
|
||||
preloadCarImage () {
|
||||
if (this.cachedImages.car) {
|
||||
this.imageLoadStatus.car = true
|
||||
@@ -210,9 +236,11 @@ export default {
|
||||
this.initCanvas()
|
||||
await this.loadMapImage()
|
||||
this.loading.close()
|
||||
return true
|
||||
} catch (e) {
|
||||
this.$message.error(`数据加载失败: ${e.message || '未知错误'}`)
|
||||
this.loading.close()
|
||||
return false
|
||||
}
|
||||
},
|
||||
async _getMapInfoByCode () {
|
||||
@@ -372,7 +400,7 @@ export default {
|
||||
20,
|
||||
20
|
||||
)
|
||||
// this.ctx.restore()
|
||||
this.ctx.restore()
|
||||
},
|
||||
handleCanvasClick (event) {
|
||||
const rect = this.canvas.getBoundingClientRect()
|
||||
|
||||
@@ -1,295 +0,0 @@
|
||||
<template>
|
||||
<div class="point-cloud-map">
|
||||
<div ref="canvasContainer" class="canvas-container"></div>
|
||||
<div v-if="isLoading" class="loading-indicator">
|
||||
<i class="fa fa-circle-o-notch fa-spin"></i> 加载中...
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Application, ParticleContainer, Sprite, Graphics, Texture } from 'pixi.js'
|
||||
import { mapGetters } from 'vuex'
|
||||
import { points } from '../../config/point.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
// PixiJS核心对象
|
||||
app: null,
|
||||
pointContainer: null,
|
||||
carSprite: null,
|
||||
|
||||
// 点云数据
|
||||
allPoints: [],
|
||||
pointScale: 1.0,
|
||||
|
||||
// 小车资源
|
||||
vehicleImage: require('../../images/new/agv.png'),
|
||||
carTexture: null,
|
||||
|
||||
// WebSocket
|
||||
socket: null,
|
||||
isLoading: true,
|
||||
|
||||
// 性能控制
|
||||
lastUpdateTime: 0,
|
||||
updateInterval: 800,
|
||||
isDestroyed: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['serverUrl', 'userRole', 'carPosition']),
|
||||
},
|
||||
watch: {
|
||||
carPosition: {
|
||||
handler(newVal) {
|
||||
this.updateCarPosition(newVal)
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 使用$nextTick确保DOM完全渲染后再初始化
|
||||
this.$nextTick(() => {
|
||||
this.initPixi()
|
||||
// this.initWebSocket()
|
||||
this.init()
|
||||
window.addEventListener('resize', this.handleResize)
|
||||
setTimeout(() => {
|
||||
this.isLoading = false
|
||||
}, 1000)
|
||||
})
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.isDestroyed = true
|
||||
|
||||
// 清理WebSocket
|
||||
if (this.socket) {
|
||||
this.socket.close()
|
||||
this.socket = null
|
||||
}
|
||||
|
||||
// 销毁Pixi应用
|
||||
if (this.app) {
|
||||
this.app.destroy()
|
||||
const container = this.$refs.canvasContainer
|
||||
if (container && container.children.length > 0) {
|
||||
container.removeChild(container.children[0])
|
||||
}
|
||||
this.app = null
|
||||
}
|
||||
|
||||
// 清理资源
|
||||
if (this.carTexture) {
|
||||
this.carTexture.destroy()
|
||||
this.carTexture = null
|
||||
}
|
||||
|
||||
window.removeEventListener('resize', this.handleResize)
|
||||
this.allPoints = []
|
||||
},
|
||||
methods: {
|
||||
async initPixi() {
|
||||
// 确保容器元素存在
|
||||
const container = this.$refs.canvasContainer
|
||||
if (!container) {
|
||||
console.error('Canvas容器未找到')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
// PixiJS v8+ 使用 Application.init() 替代 new Application()
|
||||
this.app = await Application.init({
|
||||
width: container.clientWidth,
|
||||
height: container.clientHeight,
|
||||
backgroundColor: 0x0c0c0c,
|
||||
antialias: true,
|
||||
resolution: window.devicePixelRatio || 1,
|
||||
autoDensity: true,
|
||||
})
|
||||
|
||||
// PixiJS v8+ 使用 canvas 属性替代 view 属性
|
||||
if (this.app.canvas) {
|
||||
container.appendChild(this.app.canvas)
|
||||
} else {
|
||||
console.error('PixiJS未能创建有效的canvas')
|
||||
return
|
||||
}
|
||||
|
||||
// 创建点容器 - 使用ParticleContainer提高性能
|
||||
this.pointContainer = new ParticleContainer(10000, {
|
||||
position: true,
|
||||
rotation: true,
|
||||
tint: true,
|
||||
alpha: true
|
||||
})
|
||||
this.app.stage.addChild(this.pointContainer)
|
||||
|
||||
// 加载小车纹理
|
||||
this.carTexture = await Texture.fromURL(this.vehicleImage)
|
||||
this.initCar()
|
||||
} catch (error) {
|
||||
console.error('Pixi初始化失败:', error)
|
||||
}
|
||||
},
|
||||
|
||||
initCar() {
|
||||
if (!this.carTexture) {
|
||||
console.error('小车纹理未加载')
|
||||
return
|
||||
}
|
||||
|
||||
this.carSprite = new Sprite(this.carTexture)
|
||||
this.carSprite.anchor.set(0.5) // 设置锚点为中心
|
||||
this.carSprite.width = 30
|
||||
this.carSprite.height = 30
|
||||
this.app.stage.addChild(this.carSprite)
|
||||
|
||||
if (this.carPosition) {
|
||||
this.updateCarPosition(this.carPosition)
|
||||
}
|
||||
},
|
||||
|
||||
updateCarPosition(position) {
|
||||
if (!this.carSprite || !position) return
|
||||
|
||||
this.carSprite.x = position.x * this.pointScale
|
||||
this.carSprite.y = position.y * this.pointScale
|
||||
this.carSprite.rotation = position.angle * (Math.PI / 180) // 转换为弧度
|
||||
},
|
||||
|
||||
initWebSocket() {
|
||||
const wsHost = this.serverUrl.replace(/^https?:\/\//, '')
|
||||
this.socket = new WebSocket(`ws://${wsHost}/webSocket/PointCloudData/${this.userRole}`)
|
||||
|
||||
this.socket.onopen = () => {
|
||||
console.log('WebSocket连接已建立')
|
||||
this.isLoading = false
|
||||
}
|
||||
|
||||
this.socket.onmessage = (event) => {
|
||||
if (this.isDestroyed) return
|
||||
|
||||
try {
|
||||
const now = Date.now()
|
||||
if (now - this.lastUpdateTime < this.updateInterval) return
|
||||
this.lastUpdateTime = now
|
||||
|
||||
const pointData = JSON.parse(event.data)
|
||||
this.updatePointCloud(pointData.data)
|
||||
} catch (error) {
|
||||
console.error('解析点云数据失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
this.socket.onclose = (event) => {
|
||||
console.log('WebSocket连接已关闭,代码:', event.code)
|
||||
this.isLoading = true
|
||||
setTimeout(() => this.initWebSocket(), 3000)
|
||||
}
|
||||
|
||||
this.socket.onerror = (error) => {
|
||||
console.error('WebSocket错误:', error)
|
||||
this.isLoading = true
|
||||
}
|
||||
},
|
||||
|
||||
updatePointCloud(points) {
|
||||
if (!Array.isArray(points) || points.length === 0) return
|
||||
|
||||
// 去重逻辑
|
||||
const existingPoints = {}
|
||||
this.allPoints.forEach(point => {
|
||||
existingPoints[`${point.x},${point.y}`] = true
|
||||
})
|
||||
|
||||
const newUniquePoints = points.filter(point => {
|
||||
const key = `${point.x},${point.y}`
|
||||
if (!existingPoints[key]) {
|
||||
existingPoints[key] = true
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
this.allPoints = [...this.allPoints, ...newUniquePoints]
|
||||
|
||||
// 限制总点数
|
||||
const maxPoints = 5000
|
||||
if (this.allPoints.length > maxPoints) {
|
||||
this.allPoints = this.allPoints.slice(-maxPoints)
|
||||
}
|
||||
|
||||
// 清空容器
|
||||
this.pointContainer.removeChildren()
|
||||
|
||||
// 添加新点 - 使用Graphics批量绘制
|
||||
const graphics = new Graphics()
|
||||
graphics.beginFill(0xFFFFFF, 0.8)
|
||||
|
||||
this.allPoints.forEach(point => {
|
||||
graphics.drawCircle(
|
||||
point.x * this.pointScale,
|
||||
point.y * this.pointScale,
|
||||
1
|
||||
)
|
||||
})
|
||||
|
||||
graphics.endFill()
|
||||
this.pointContainer.addChild(graphics)
|
||||
},
|
||||
|
||||
handleResize() {
|
||||
if (!this.app || !this.$refs.canvasContainer) return
|
||||
|
||||
const container = this.$refs.canvasContainer
|
||||
this.app.renderer.resize(
|
||||
container.clientWidth,
|
||||
container.clientHeight
|
||||
)
|
||||
},
|
||||
|
||||
init () {
|
||||
this.isLoading = false
|
||||
const pointData = points.data
|
||||
this.updatePointCloud(pointData);
|
||||
setTimeout(() => {
|
||||
const arr = [{x: 2, y: 2}, {x: 4, y: 4}]
|
||||
this.updatePointCloud(arr);
|
||||
}, 2000)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.point-cloud-map
|
||||
position relative
|
||||
width 100%
|
||||
height calc(100% - 1rem)
|
||||
margin .14rem 0
|
||||
background-color rgba(4, 33, 58, 70%)
|
||||
box-shadow inset 1px 1px 7px 2px #4d9bcd
|
||||
overflow hidden
|
||||
|
||||
.canvas-container
|
||||
width 100%
|
||||
height 100%
|
||||
position relative
|
||||
z-index 0
|
||||
|
||||
.loading-indicator
|
||||
position absolute
|
||||
top 50%
|
||||
left 50%
|
||||
transform translate(-50%, -50%)
|
||||
background-color rgba(255, 255, 255, 0.8)
|
||||
padding .01rem .02rem
|
||||
border-radius 4px
|
||||
box-shadow 0 2px 10px rgba(0, 0, 0, 0.1)
|
||||
font-size .12rem
|
||||
color #333
|
||||
z-index 100
|
||||
display flex
|
||||
align-items center
|
||||
</style>
|
||||
Reference in New Issue
Block a user