Kaynağa Gözat

任务模块-直播页面新增轨迹

tags/v1.0.0^2
余菲 2 yıl önce
ebeveyn
işleme
e915fe8e6a
5 değiştirilmiş dosya ile 268 ekleme ve 13 silme
  1. BIN
      src/assets/point/geo.png
  2. +7
    -7
      src/components/PositionMsg/util.js
  3. +232
    -4
      src/views/task-manage/all-task/components/LiveDrawer.vue
  4. +2
    -2
      src/views/task-manage/all-task/index.vue
  5. +27
    -0
      src/views/task-manage/all-task/tools/style.js

BIN
src/assets/point/geo.png Dosyayı Görüntüle

Önce Sonra
Genişlik: 50  |  Yükseklik: 50  |  Boyut: 2.1KB

+ 7
- 7
src/components/PositionMsg/util.js Dosyayı Görüntüle

@@ -1,9 +1,9 @@
import 'ol/ol.css'
import { Style, Icon } from 'ol/style'
import imgAwait from '../../assets/point/await.png'
import imgChecked from '../../assets/point/checked.png'
import imgIgnored from '../../assets/point/ignored.png'
import imgSelected from '../../assets/point/selected.png'
import imgAwait from '@/assets/point/await.png'
import imgChecked from '@/assets/point/checked.png'
import imgIgnored from '@/assets/point/ignored.png'
import imgSelected from '@/assets/point/selected.png'

// 矢量图标样式
export const styleList = [
@@ -19,7 +19,7 @@ export const styleList = [
new Style({
image: new Icon({
anchor: [0.5, 0.5],
src: imgAwait,
src: imgChecked,
crossOrigin: '',
scale: [1, 1],
rotateWithView: true
@@ -28,7 +28,7 @@ export const styleList = [
new Style({
image: new Icon({
anchor: [0.5, 0.5],
src: imgChecked,
src: imgIgnored,
crossOrigin: '',
scale: [1, 1],
rotateWithView: true
@@ -37,7 +37,7 @@ export const styleList = [
new Style({
image: new Icon({
anchor: [0.5, 0.5],
src: imgIgnored,
src: imgAwait,
crossOrigin: '',
scale: [1, 1],
rotateWithView: true

+ 232
- 4
src/views/task-manage/all-task/components/LiveDrawer.vue Dosyayı Görüntüle

@@ -1,13 +1,28 @@
<template>
<n-drawer v-bind="getDrawerOptions" @update:show="handleDrawerColse">
<n-drawer-content closable title="飞行直播">
飞行直播
<div class="main_container">
<div id="live-map" />
</div>
</n-drawer-content>
</n-drawer>
</template>

<script>
import { h, defineComponent, computed, reactive, toRefs } from 'vue'
import { defineComponent, computed, reactive, toRefs, onMounted } from 'vue'
import { Map, View, Feature } from 'ol'
import 'ol/ol.css'
import { Tile, Vector as VectorLayer } from 'ol/layer'
import LineString from 'ol/geom/LineString'
import Point from 'ol/geom/Point'
import { XYZ, Vector as VectorSource } from 'ol/source'
import { transform, fromLonLat } from 'ol/proj'
import { getVectorContext } from 'ol/render'
import VectorContext from 'ol/render/VectorContext'
import { Draw } from 'ol/interaction'
import { toRaw } from '@vue/reactivity'
import * as control from 'ol/control'
import { styleList } from '../tools/style.js'

export default defineComponent({
name: 'LiveDrawer',
@@ -28,9 +43,43 @@ export default defineComponent({
},
setup(props, { emit }) {
const data = reactive({

mapData: null,
view: null,
liveTrackLayer: null,
lineTrackLayer: null,
trackInfo: null,
socket: null,
// 预计航线数据
lineTrajectoryList: [
{ lng: '118.765591', lat: '32.050993' },
{ lng: '118.665591', lat: '32.150993' },
{ lng: '118.565591', lat: '32.070993' },
{ lng: '118.465591', lat: '32.020993' },
{ lng: '118.365591', lat: '32.110993' },
{ lng: '118.265591', lat: '32.080993' },
{ lng: '118.165591', lat: '32.150993' },
{ lng: '118.765591', lat: '32.150993' },
{ lng: '118.665591', lat: '32.050993' },
{ lng: '118.565591', lat: '32.170993' },
{ lng: '118.465591', lat: '32.010993' },
{ lng: '118.365591', lat: '32.060993' },
{ lng: '118.265591', lat: '32.180993' },
{ lng: '118.165591', lat: '32.050993' }
],
// 轨迹数据
trackList: [
{ lng: '118.765591', lat: '32.050993' },
{ lng: '118.665591', lat: '32.150993' },
{ lng: '118.565591', lat: '32.070993' },
{ lng: '118.465591', lat: '32.020993' },
{ lng: '118.365591', lat: '32.110993' },
{ lng: '118.265591', lat: '32.080993' },
{ lng: '118.165591', lat: '32.150993' }
],
trajectoryList: [], // 历史轨迹坐标数据
disdance: null,
animating: null
})

/* 获取抽屉的信息 */
const getDrawerOptions = computed(() => {
return {
@@ -43,6 +92,174 @@ export default defineComponent({
emit('update:visible', false)
}

onMounted(() => {
initMap()
// 加载航线
initTrack(formatTradeList(data.lineTrajectoryList), 'lineTrackLayer', 'lineRoute')
// 加载历史轨迹和实时轨迹
setLiveTrack(formatTradeList(data.trackList))
})

/* 初始化地图 */
const initMap = function() {
const layers = [
new Tile({
visible: true,
source: new XYZ({
url: 'https://tianditu.t-aaron.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=f82bb2fd8115c7fb576a8b2fcf738523'
})
})
]

data.view = new View({
maxZoom: 18,
zoom: 5,
center: transform([118.837886, 32.057175], 'EPSG:4326', 'EPSG:3857')
})
data.mapData = new Map({
layers: layers,
target: 'live-map',
view: data.view,
controls: control.defaults({
attribution: false,
rotate: false,
zoom: false
})
})
data.mapData.render()
}

/* 处理轨迹列表 */
const formatTradeList = function(trackList) {
return trackList.map((item) =>
fromLonLat([parseFloat(item.lng), parseFloat(item.lat)])
)
}

/* 初始化轨迹 */
const initTrack = function(coordinate, layer, routeType) {
let vectorLayer = null
const route = new LineString(coordinate)
const routeFeature = new Feature({
type: routeType,
geometry: route
})
const startMarker = new Feature({
type: 'icon',
geometry: new Point(route.getFirstCoordinate())
})
const position = startMarker.getGeometry().clone()
const geoMarker = new Feature({
type: 'geoMarker',
geometry: position
})
geoMarker.setProperties({ type: 'geoMarker' }, false)
if (data.liveTrackLayer) {
data.liveTrackLayer.setSource(
new VectorSource({
features: [geoMarker, routeFeature]
})
)
vectorLayer = data.liveTrackLayer
} else {
vectorLayer = new VectorLayer({
source: new VectorSource({
features: [geoMarker, routeFeature]
}),
style: function(feature) {
return styleList[feature.get('type')]
}
})
}
data[layer] = vectorLayer
data.mapData.addLayer(data[layer])
data.view.fit(route, { padding: [50, 50, 50, 50] })
return {
vectorLayer,
geoMarker,
route,
position
}
}

/* 轨迹改变 */
const changeTrack = (event) => {
try {
const vectorContext = getVectorContext(event)
vectorContext.setStyle(styleList['geoMarker'])
VectorContext.drawGeometry(data.trackInfo.position)
vectorContext.drawGeometry(data.trackInfo.route)
data.mapData.render()
} catch {
console.log(event)
}
}

/* 加载实时轨迹 */
const setLiveTrack = function(hisTrackList) {
data.animating = false
data.disdance = 0
if (hisTrackList.length > 1) {
data.trackInfo = initTrack(hisTrackList, 'liveTrackLayer', 'route')
if (data.trackInfo.vectorLayer) {
data.liveTrackLayer.on('change', changeTrack)
}
}

// 两秒钟获取一次数据
data.socket = setInterval(() => {
// getTrackdata({ inspectionId: id }).then((res) => {
// const coordinate = fromLonLat([res.data.lng, res.data.lat])
// const unUseableCoordinate = !coordinate.every((item) => !isNaN(item))
// if (unUseableCoordinate) return
// // 赋值动态无人机坐标
// if (coordinate.length) {
// data.trajectoryList.lng = coordinate[0]
// data.trajectoryList.lat = coordinate[1]
// }

// data.trackList.push(coordinate)
// if (data.trackList.length > 1 && !data.trackInfo) {
// initTrack(data.trackList)
// }
// if (data.trackInfo) {
// data.trackInfo.route.appendCoordinate(coordinate)
// data.trackInfo.vectorLayer.getSource().changed()
// data.trackInfo.position.setCoordinates(coordinate)
// }
// })
}, 2000)
// 移动要素
const moveFeature = function(event) {
var lastTime
const speed = Number(50)
const time = event.frameState.time
const elapsedTime = time - lastTime
data.disdance = (data.disdance + (speed * elapsedTime) / 1e6) % 2
if (data.disdance > 1) {
stopAnimation(data.trackInfo)
}
lastTime = time

const currentCoordinate = data.trackInfo.route.getCoordinateAt(
data.disdance > 1 ? 2 - data.disdance : data.disdance
)
data.trackInfo.position.setCoordinates(currentCoordinate)
const vectorContext = getVectorContext(event)
vectorContext.setStyle(styleList['geoMarker'])
vectorContext.drawGeometry(data.trackInfo.position)
data.mapData.render()
}

// 停止动画
const stopAnimation = function(trackInfo) {
const { vectorLayer, geoMarker } = trackInfo
data.animating = false
geoMarker.setGeometry(trackInfo.position)
vectorLayer.un('postrender', moveFeature)
}
}

return {
...toRefs(data),
getDrawerOptions,
@@ -56,4 +273,15 @@ export default defineComponent({
.n-button+.n-button{
margin-left: 30px;
}
.main_container {
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
}
#live-map {
width: 100%;
height: 100%;
}

</style>

+ 2
- 2
src/views/task-manage/all-task/index.vue Dosyayı Görüntüle

@@ -5,7 +5,7 @@
<DataTable
ref="tableRef"
:columns="columns"
:data="data"
:request="loadDataTable"
:row-key="(row) => row.id"
size="large"
>
@@ -29,7 +29,7 @@
<!-- 新增、编辑弹窗 -->
<TaskModal v-if="modalShow" v-model:visible="modalShow" :type="modalType" :data="rowData" @reload="handleSearch" />
<!-- 直播抽屉 -->
<LiveDrawer v-model:visible="liveDrawer" :data="rowData" />
<LiveDrawer v-if="liveDrawer" v-model:visible="liveDrawer" :data="rowData" />
<!-- 轨迹回放 -->
<DemandDrawer v-model:visible="demandDrawer" :data="rowData" />
<!-- 问题核实 -->

+ 27
- 0
src/views/task-manage/all-task/tools/style.js Dosyayı Görüntüle

@@ -0,0 +1,27 @@
import { Style, Icon, Stroke } from 'ol/style'
import imgGeo from '@/assets/point/geo.png'
export const styleList = {
route: new Style({
stroke: new Stroke({
width: 2,
color: 'red'
})
}),
geoMarker: new Style({
image: new Icon({
anchor: [0.5, 0.5],
src: imgGeo,
crossOrigin: '',
scale: [1, 1],
rotateWithView: true
})
}),
lineRoute: new Style({
stroke: new Stroke({
width: 2,
color: 'yellow',
lineDash: [5]
})
})
}


Yükleniyor…
İptal
Kaydet