启用 mapbox 地图控件,优化相关交互逻辑。

This commit is contained in:
hym 2025-11-25 21:09:38 +08:00
parent 51478c40c9
commit 20444e9243
1 changed files with 206 additions and 57 deletions

View File

@ -26,10 +26,12 @@
</el-radio-group> </el-radio-group>
</div> </div>
<div class="left4" v-if="radio == '数据样品集'"> <div class="left4" v-if="radio == '数据样品集'">
<div v-for="(item, index) in dataList" :key="index" :id="item.tsy_id" class="left4_1" > <div v-for="(item, index) in dataList" :key="index" :id="item.tsy_id" class="left4_1">
<div class="left4_top"> <div class="left4_top">
<p class="rule-text">编号规则:航次号_潜次号_设备类型_数据样品类型</p> <p class="rule-text">编号规则:航次号_潜次号_设备类型_数据样品类型</p>
<p @click="openList(item, 'list')" style="font-weight: 400;font-size: 14px;cursor: pointer;color: #409eff" >{{ item.dataset_name }} <span class="mileage">{{ item.file_total }}</span></p> <p @click="openList(item, 'list')"
style="font-weight: 400;font-size: 14px;cursor: pointer;color: #409eff">{{ item.dataset_name }} <span
class="mileage">{{ item.file_total }}</span></p>
<span class="org">{{ item.create_time }}</span> <span class="org">{{ item.create_time }}</span>
</div> </div>
<ul v-show="currenId == item.tsy_id && fold"> <ul v-show="currenId == item.tsy_id && fold">
@ -40,7 +42,8 @@
<div class="left4_list"> <div class="left4_list">
<div class="list1"> <div class="list1">
<p>航次</p> <p>航次</p>
<span class="hover-color" style="color: #409eff" @click="turnDeatilPage(item)">{{ item.voyage_name }}</span> <span class="hover-color" style="color: #409eff" @click="turnDeatilPage(item)">{{ item.voyage_name
}}</span>
</div> </div>
<div class="list1"> <div class="list1">
<p>平台类型</p> <p>平台类型</p>
@ -82,7 +85,8 @@
<div class="left4_top"> <div class="left4_top">
<p :style="currentVoyage === item.tsy_id ? 'color: #409eff' : ''"> <p :style="currentVoyage === item.tsy_id ? 'color: #409eff' : ''">
<span style="color: #409eff" @click="turnDeatilPage(item)">{{ item.voyage_name }}</span> <span style="color: #409eff" @click="turnDeatilPage(item)">{{ item.voyage_name }}</span>
<span class="mileage">{{ item.voyage_mileage }}海里</span></p> <span class="mileage">{{ item.voyage_mileage }}海里</span>
</p>
<span class="org">{{ item.funding_org }}</span> <span class="org">{{ item.funding_org }}</span>
</div> </div>
<div class="left4_list"> <div class="left4_list">
@ -115,11 +119,15 @@
<span>{{ item.serect_status == 'Active' ? '是' : '否' }}</span> <span>{{ item.serect_status == 'Active' ? '是' : '否' }}</span>
</div> </div>
<div class="btns"> <div class="btns">
<el-button v-if="!item.highlight" icon="el-icon-s-opportunity" circle @click="addHighlightLayer(item.voyage_name, index)" /> <el-button v-if="!item.highlight" icon="el-icon-s-opportunity" circle
<el-button v-if="item.highlight" type="primary" icon="el-icon-s-opportunity" circle @click="clearHighlight" /> @click="addHighlightLayer(item.voyage_name, index)" />
<el-button v-if="!item.show" icon="el-icon-view" circle @click="addSingleLineImg(item.voyage_name, index)" /> <el-button v-if="item.highlight" type="primary" icon="el-icon-s-opportunity" circle
<el-button v-if="item.show" type="primary" icon="el-icon-view" circle @click="removeSingleLineImg(item.voyage_name, index)" /> @click="clearHighlight(item.voyage_name, index)" />
<el-button icon="el-icon-location-information" circle /> <el-button v-if="!item.show" icon="el-icon-view" circle
@click="addSingleLineImg(item.voyage_name, index)" />
<el-button v-if="item.show" type="primary" icon="el-icon-view" circle
@click="removeSingleLineImg(item.voyage_name, index)" />
<!-- <el-button icon="el-icon-location-information" circle /> -->
</div> </div>
</div> </div>
</div> </div>
@ -139,58 +147,46 @@
</div> </div>
</div> </div>
<!-- 航次名称弹窗--> <!-- 航次名称弹窗-->
<el-dialog <el-dialog title="请选择航次名称" :visible.sync="dialog1" width="1000px">
title="请选择航次名称" <el-table ref="tableData1" border highlight-current-row @current-change="handleCurrentChange1" max-height="480"
:visible.sync="dialog1" :data="tableData1" :header-cell-style="{ background: '#dddfe6', color: '#555960', textAlign: 'center' }"
width="1000px" :cell-style="{ textAlign: 'center' }">
> <el-table-column type="index" label="#" width="50" />
<el-table ref="tableData1" border highlight-current-row @current-change="handleCurrentChange1" max-height="480" :data="tableData1" :header-cell-style="{ background: '#dddfe6',color: '#555960',textAlign: 'center' }" :cell-style="{ textAlign: 'center' }">
<el-table-column type="index" label="#" width="50"/>
<el-table-column prop="name" label="航次名称" /> <el-table-column prop="name" label="航次名称" />
</el-table> </el-table>
</el-dialog> </el-dialog>
<!-- 平台类型弹窗--> <!-- 平台类型弹窗-->
<el-dialog <el-dialog title="请选择平台类型" :visible.sync="dialog2" width="1000px">
title="请选择平台类型" <el-table ref="tableData2" border @current-change="handleCurrentChange2" :data="tableData2" max-height="480"
:visible.sync="dialog2" :header-cell-style="{ background: '#dddfe6', color: '#555960', textAlign: 'center' }"
width="1000px" :cell-style="{ textAlign: 'center' }">
> <el-table-column type="index" label="#" width="50" />
<el-table ref="tableData2" border @current-change="handleCurrentChange2" :data="tableData2" max-height="480" :header-cell-style="{ background: '#dddfe6',color: '#555960',textAlign: 'center' }" :cell-style="{ textAlign: 'center' }">
<el-table-column type="index" label="#" width="50"/>
<el-table-column prop="name" label="平台类型名称" /> <el-table-column prop="name" label="平台类型名称" />
<el-table-column prop="value" label="英文类型名称" /> <el-table-column prop="value" label="英文类型名称" />
</el-table> </el-table>
</el-dialog> </el-dialog>
<!-- 设备类型弹窗--> <!-- 设备类型弹窗-->
<el-dialog <el-dialog title="请选择设备类型" :visible.sync="dialog3" width="1000px">
title="请选择设备类型" <el-table ref="tableData3" border @current-change="handleCurrentChange3" :data="tableData3" max-height="480"
:visible.sync="dialog3" :header-cell-style="{ background: '#dddfe6', color: '#555960', textAlign: 'center' }"
width="1000px" :cell-style="{ textAlign: 'center' }">
> <el-table-column type="index" label="#" width="50" />
<el-table ref="tableData3" border @current-change="handleCurrentChange3" :data="tableData3" max-height="480" :header-cell-style="{ background: '#dddfe6',color: '#555960',textAlign: 'center' }" :cell-style="{ textAlign: 'center' }">
<el-table-column type="index" label="#" width="50"/>
<el-table-column prop="name" label="设备类型名称" /> <el-table-column prop="name" label="设备类型名称" />
<el-table-column prop="value" label="英文名称" /> <el-table-column prop="value" label="英文名称" />
</el-table> </el-table>
</el-dialog> </el-dialog>
<!-- 数据样品类型弹窗--> <!-- 数据样品类型弹窗-->
<el-dialog <el-dialog title="请选择数据样品类型" :visible.sync="dialog4" width="1000px">
title="请选择数据样品类型" <el-table ref="tableData4" border @current-change="handleCurrentChange4" :data="tableData4" max-height="480"
:visible.sync="dialog4" :header-cell-style="{ background: '#dddfe6', color: '#555960', textAlign: 'center' }"
width="1000px" :cell-style="{ textAlign: 'center' }">
> <el-table-column type="index" label="#" width="50" />
<el-table ref="tableData4" border @current-change="handleCurrentChange4" :data="tableData4" max-height="480" :header-cell-style="{ background: '#dddfe6',color: '#555960',textAlign: 'center' }" :cell-style="{ textAlign: 'center' }">
<el-table-column type="index" label="#" width="50"/>
<el-table-column prop="name" label="数据样品类型类型名称" /> <el-table-column prop="name" label="数据样品类型类型名称" />
<el-table-column prop="value" label="英文名称" /> <el-table-column prop="value" label="英文名称" />
</el-table> </el-table>
</el-dialog> </el-dialog>
<!-- 航次信息弹窗--> <!-- 航次信息弹窗-->
<el-dialog <el-dialog title="航次信息" :visible.sync="dialog5" width="800px">
title="航次信息"
:visible.sync="dialog5"
width="800px"
>
<div class="detail_b"> <div class="detail_b">
<h3 style="padding-bottom: 10px;">{{ voyageInfo.voyage_name }}</h3> <h3 style="padding-bottom: 10px;">{{ voyageInfo.voyage_name }}</h3>
<p>{{ voyageInfo.voyage_remark }}</p> <p>{{ voyageInfo.voyage_remark }}</p>
@ -240,6 +236,10 @@ import Cookies from 'js-cookie'
import { import {
setImageryViewModels setImageryViewModels
} from '@/utils/common' } from '@/utils/common'
import Vue from 'vue'
import { loadVectorLayer } from '@/utils/vector-layer-utils'
import { ColorGenerator } from '@/utils/color-generator';
import { handleWheel } from "@/utils/mapbox-utils";
const Cesium = window.Cesium const Cesium = window.Cesium
export default { export default {
@ -362,7 +362,8 @@ export default {
}, },
mounted() { mounted() {
this.imageryViewModels = setImageryViewModels(this.CesiumHostAddr) this.imageryViewModels = setImageryViewModels(this.CesiumHostAddr)
this.initCesium() this.initMapbox()
// this.initCesium()
}, },
methods: { methods: {
// //
@ -452,17 +453,27 @@ export default {
const arr = res.page.records const arr = res.page.records
if (this.radio === '航次') { if (this.radio === '航次') {
if (arr.length) { if (arr.length) {
let i = 0;
const colors = ColorGenerator.generateDivergingColors(arr.length);
arr.forEach(item => { arr.forEach(item => {
item.highlight = false item.highlight = false
item.show = true item.show = true
this.addSingleLineImg(item.voyage_name, null) // this.addSingleLineImg(item.voyage_name, null)
//
loadVectorLayer(item.voyage_name, ["line", "symbol"], [colors[i], colors[i]], "visible", "dataSearch", "dsds");
i++;
}) })
} }
this.dataList = arr this.dataList = arr
} }
if (this.radio === '数据样品集') { if (this.radio === '数据样品集') {
try {
this.getDataPoints(arr) this.getDataPoints(arr)
} }
catch (err) {
console.log(err);
}
}
}) })
}, },
// //
@ -481,8 +492,8 @@ export default {
this.dataList[i].highlight = true; this.dataList[i].highlight = true;
}, },
// //
clearHighlight() { clearHighlight(voyageName, i) {
this.dataList.map(item => {item.highlight = false}) this.dataList.map(item => { item.highlight = false })
// //
if (this.highlightLayer) { if (this.highlightLayer) {
this.viewer.imageryLayers.remove(this.highlightLayer); this.viewer.imageryLayers.remove(this.highlightLayer);
@ -491,7 +502,13 @@ export default {
}, },
// //
addSingleLineImg(voyageName, i) { addSingleLineImg(voyageName, i) {
if (i !== null) {
this.dataList[i].show = true;
}
//
Vue.config.maps["dataSearch"].setLayoutProperty(`vector-${voyageName}-symbol`, "visibility", "visible");
Vue.config.maps["dataSearch"].setLayoutProperty(`vector-${voyageName}-line`, "visibility", "visible");
return;
// //
if (this.trackLayerMap[voyageName]) { if (this.trackLayerMap[voyageName]) {
console.warn(`航次 ${voyageName} 的轨迹图层已存在`); console.warn(`航次 ${voyageName} 的轨迹图层已存在`);
@ -518,6 +535,16 @@ export default {
// //
removeSingleLineImg(voyageName, i) { removeSingleLineImg(voyageName, i) {
if (i !== null) {
this.dataList[i].show = false;
}
//
// let visibility = Vue.config.maps["dataSearch"].getLayoutProperty(`vector-${voyageName}-symbol`, "visibility");
// visibility = visibility == "visible" ? "none" : "visible";
Vue.config.maps["dataSearch"].setLayoutProperty(`vector-${voyageName}-symbol`, "visibility", "none");
Vue.config.maps["dataSearch"].setLayoutProperty(`vector-${voyageName}-line`, "visibility", "none");
return;
const layerInstance = this.trackLayerMap[voyageName]; const layerInstance = this.trackLayerMap[voyageName];
if (layerInstance) { if (layerInstance) {
// CesiumimageryLayers // CesiumimageryLayers
@ -581,7 +608,7 @@ export default {
}, },
// //
clearAll() { clearAll() {
this.clearHighlight() // this.clearHighlight()
if (this.trackLayerMap.length) { if (this.trackLayerMap.length) {
this.trackLayerMap.forEach(layer => { this.trackLayerMap.forEach(layer => {
this.viewer.imageryLayers.remove(layer); this.viewer.imageryLayers.remove(layer);
@ -597,9 +624,15 @@ export default {
// //
getDataPoints(arr) { getDataPoints(arr) {
if (!arr.length) return false if (!arr.length) return false
let i = 0;
const colors = ColorGenerator.generateDivergingColors(arr.length);
arr.forEach(item => { arr.forEach(item => {
this.addSingleLineImg(item.voyage_name, null) // this.addSingleLineImg(item.voyage_name, null)
this.divingImage(item) //
// loadVectorLayer(item.voyage_name, ["line", "symbol"], [colors[i], colors[i]], "visible", "dataSearch", "dsds");
i++;
// this.dataList[i].show = true;
// this.divingImage(item)
}) })
const voyageList = arr const voyageList = arr
voyageList.map(item => { voyageList.map(item => {
@ -610,8 +643,14 @@ export default {
}).then(res => { }).then(res => {
item.sampleArray = res.array item.sampleArray = res.array
if (res.array.length) { if (res.array.length) {
let i = 0;
const colors = ColorGenerator.generateDivergingColors(res.array.length);
res.array.forEach(sample => { res.array.forEach(sample => {
this.sampleLineImage(sample) console.log(sample);
// this.sampleLineImage(sample)
//
// loadVectorLayer(sample.sample_name, ["line", "symbol"], [colors[i], colors[i]], "visible", "dataSearch", "dsds");
i++;
}) })
} }
}) })
@ -624,8 +663,13 @@ export default {
item.sampleArray = res.array item.sampleArray = res.array
// //
if (res.array.length) { if (res.array.length) {
let i = 0;
const colors = ColorGenerator.generateDivergingColors(res.array.length);
res.array.forEach(sample => { res.array.forEach(sample => {
this.sampleLineImage(sample) // this.sampleLineImage(sample)
//
// loadVectorLayer(sample.sample_name, ["line", "symbol"], [colors[i], colors[i]], "visible", "dataSearch", "dsds");
i++;
}) })
} }
}) })
@ -635,6 +679,91 @@ export default {
console.log(this.dataList) console.log(this.dataList)
}, },
// mapbox
initMapbox() {
window.mapboxgl.accessToken = 'pk.eyJ1IjoicWRod2kiLCJhIjoiY2xiaXppcjEyMGNhMjNwbzVrcHl4d20zOSJ9.0ETMJM3-zllFh2GRrRVUZg'
const map = new window.mapboxgl.Map({
container: 'cesiumContainerData',
// style: 'mapbox://styles/mapbox/standard',
style: {
"version": 8,
"name": "default_style",
// mapbox使
"sprite": `${Vue.config.baseUrl}/oe/${Vue.config.wwwrootBaseUrl}/sprites/sprite`,
// 使
"glyphs": "mapbox://fonts/mapbox/{fontstack}/{range}.pbf",
// glyphs 404
// "glyphs": `${Vue.config.baseUrl}/oe/${Vue.config.wwwrootBaseUrl}/glyphs/{fontstack}/{range}.pbf`,
"sources": {
"影像地图": {
"type": "raster",
"tiles": [`${Vue.config.baseUrl}/geoserver/gwc/service/wmts/rest/ougp:world/EPSG:900913/EPSG:900913:{z}/{y}/{x}?format=image/jpeg`],
"tileSize": 256,
// "minzoom": 0,
// "maxzoom": baseMapMaxZoom
}
},
"layers": [
{
"id": "影像地图",
"type": "raster",
"source": "影像地图",
"layout": { visibility: "visible" },
// "minzoom": 0,
// "maxzoom": baseMapMaxZoom
}
]
},
config: {
basemap: {
theme: 'monochrome',
lightPreset: 'night'
}
},
zoom: 5,
center: [113, 15.5],
minZoom: 2,
maxZoom: 29,
trackResize: true,
scrollZoom: false, //
//
localIdeographFontFamily: "Microsoft YoHei, 'Noto Sans', 'Noto Sans CJK SC', sans-serif",
pitch: 0,
bearing: 0,
// maxBounds: [[-180, -90], [180, 90]],// Set the map's geographical boundaries.
antialias: true,
attributionControl: false,
boxZoom: true,//trueshift
preserveDrawingBuffer: false,//truecanvas使pngmap.getCanvas().toDataURL()false
projection: 'equirectangular', // 26
});
Vue.config.maps["dataSearch"] = map;
//
window.addEventListener('resize', (event) => {
map.resize();
// // maps.forEach((key: string, value: any) => {
// // console.log(`${key}: ${value}`);
// // });
// for (let [key, value] of Object.entries(maps)) {
// // value.resize();
// }
// Object.values(maps).forEach((map) => {
// map.resize();
// });
});
handleWheel("dataSearch");
map.on('load', () => {
// 线
loadVectorLayer("GSHHS_f_L1", ["line"], ["#5c71c3"], "visible", "dataSearch", 'ougp');
// 线
// loadVectorLayer("contour-4500m", ["line"], ["#FEFEFE"], "visible", "dataSearch", 'ougp');
// loadVectorLayer("contour-6000m", ["line"], ["#FEFEFE"], "visible", "dataSearch", 'ougp');
});
},
// cesium // cesium
initCesium() { initCesium() {
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkY2Y5NWY2Ni1mODQ1LTQ3YTUtYjc4Zi1jYzhjMGI2YzcxMWYiLCJpZCI6MTI5ODMwLCJpYXQiOjE2Nzk0Njk5NTd9.DTH54ioOH-HLqeNIetBe9hFyrPOX2Vp1AQmZzw8TIZ4' Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkY2Y5NWY2Ni1mODQ1LTQ3YTUtYjc4Zi1jYzhjMGI2YzcxMWYiLCJpZCI6MTI5ODMwLCJpYXQiOjE2Nzk0Njk5NTd9.DTH54ioOH-HLqeNIetBe9hFyrPOX2Vp1AQmZzw8TIZ4'
@ -723,7 +852,7 @@ export default {
}, },
turnDeatilPage(item) { turnDeatilPage(item) {
this.dialog5 = true this.dialog5 = true
regInfo({voyage_name: item.voyage_name}).then(res => { regInfo({ voyage_name: item.voyage_name }).then(res => {
this.voyageInfo = res.map.voyage this.voyageInfo = res.map.voyage
}) })
}, },
@ -738,9 +867,17 @@ export default {
}, },
shousuo() { shousuo() {
this.show = true this.show = true
// resize
setTimeout(() => {
Vue.config.maps["dataSearch"].resize();
}, 10);
}, },
toshow() { toshow() {
this.show = false this.show = false
// resize
setTimeout(() => {
Vue.config.maps["dataSearch"].resize();
}, 10);
}, },
// //
openList(item, type) { openList(item, type) {
@ -782,6 +919,18 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
// #cesiumContainerData {
// // position: absolute;
// left: 0px;
// top: 0px;
// bottom: 0px;
// right: 0px;
// padding: 0px;
// margin: 0px;
// width: 100%;
// height: 100vh;
// }
.shuju { .shuju {
width: 100%; width: 100%;
height: 100%; height: 100%;
@ -1034,7 +1183,7 @@ export default {
position: absolute; position: absolute;
bottom: 0; bottom: 0;
right: 20px; right: 20px;
color: rgba(255,255, 255, 0.8); color: rgba(255, 255, 255, 0.8);
} }
} }
} }