|
@@ -0,0 +1,185 @@
|
|
|
+import {defineStore} from "pinia";
|
|
|
+import {ElMessage} from "element-plus";
|
|
|
+import {computed, createApp, markRaw, reactive, render, toRefs, watch} from "vue";
|
|
|
+import * as format from "ol/format";
|
|
|
+import * as layer from "ol/layer";
|
|
|
+import * as source from "ol/source";
|
|
|
+import * as style from "ol/style";
|
|
|
+import MapStyle from "./map-style";
|
|
|
+import * as ol from "ol";
|
|
|
+
|
|
|
+export const useShipMapStore = defineStore('shipMap', () => {
|
|
|
+ const state: any = reactive({
|
|
|
+ map: null,
|
|
|
+ zoom: 0,
|
|
|
+ layerWMS: null,
|
|
|
+ ws: {
|
|
|
+ instance: null,
|
|
|
+ layerShip: null,
|
|
|
+ overlayTrack: null,
|
|
|
+ },
|
|
|
+ trackHoverData: null
|
|
|
+ })
|
|
|
+ const initMap = (map, {trackPointDom}) => {
|
|
|
+ state.map = map
|
|
|
+ state.map.add
|
|
|
+ state.zoom = state.map.getView().getZoom()
|
|
|
+ state.map.on('movestart', e => {
|
|
|
+ map.un('pointermove', mapPointerMove)
|
|
|
+ map.un('singleclick', mapSingleClick)
|
|
|
+ })
|
|
|
+ state.map.on('moveend', e => {
|
|
|
+ state.trackHover = new Date().getTime()
|
|
|
+ state.zoom = e.map.getView().getZoom()
|
|
|
+ switchZoom()
|
|
|
+ map.on('singleclick', mapSingleClick)
|
|
|
+ map.on('pointermove', mapPointerMove)
|
|
|
+ })
|
|
|
+ state.ws.overlayTrack = new ol.Overlay({
|
|
|
+ element: trackPointDom,
|
|
|
+ autoPan: false,
|
|
|
+ offset: [0, -12],
|
|
|
+ positioning: 'bottom-center',
|
|
|
+ stopEvent: true,
|
|
|
+ })
|
|
|
+ state.map.addOverlay(state.ws.overlayTrack)
|
|
|
+ }
|
|
|
+ const mapPointerMove = (ev) => {
|
|
|
+ let pixel = ev.pixel
|
|
|
+ let feature = state.map.forEachFeatureAtPixel(pixel, function (feature) {
|
|
|
+ return feature
|
|
|
+ })
|
|
|
+ if (feature) {
|
|
|
+ state.trackHoverData = feature.get('_data')
|
|
|
+ state.ws.overlayTrack.setPosition(feature.getGeometry().getCoordinates())
|
|
|
+ } else {
|
|
|
+ state.trackHoverData = null
|
|
|
+ state.ws.overlayTrack.setPosition(undefined)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const mapSingleClick = (ev) => {}
|
|
|
+
|
|
|
+ const zoomWMS = computed(() => {
|
|
|
+ return state.zoom <= 12
|
|
|
+ })
|
|
|
+ const switchZoom = () => {
|
|
|
+ if (zoomWMS.value) {
|
|
|
+ if (state.ws.instance) {
|
|
|
+ state.ws.instance.close()
|
|
|
+ state.ws.instance = null
|
|
|
+ state.map.removeLayer(state.ws.layerShip)
|
|
|
+ state.ws.layerShip = null
|
|
|
+ }
|
|
|
+ // 瓦片
|
|
|
+ initWMS()
|
|
|
+ } else {
|
|
|
+ if (state.layerWMS) {
|
|
|
+ state.map.removeLayer(state.layerWMS)
|
|
|
+ state.layerWMS = null
|
|
|
+ }
|
|
|
+ // ws
|
|
|
+ initWebSocket()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const initWMS = () => {
|
|
|
+ const __flag = 'shipWMS'
|
|
|
+ if (!state.layerWMS) {
|
|
|
+ const _l = state.map?.getLayers().getArray().filter(v => v.get('__layerName') === __flag)
|
|
|
+ if (_l?.length > 0) {
|
|
|
+ _l.forEach(v => {
|
|
|
+ state.map.removeLayer(v)
|
|
|
+ })
|
|
|
+ }
|
|
|
+ const _tileWMS = new source.TileWMS({
|
|
|
+ url: `/geoserver-api/geoserver/redis/wms`,
|
|
|
+ params: {
|
|
|
+ 'FORMAT': 'image/png8',
|
|
|
+ 'VERSION': '1.1.1',
|
|
|
+ LAYERS: 'redis:geo_fusion_ship',
|
|
|
+ "exceptions": 'application/vnd.ogc.se_inimage',
|
|
|
+ // CQL_FILTER: CQL,
|
|
|
+ refresh: new Date().getTime()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ state.layerWMS = new layer.Tile({
|
|
|
+ source: _tileWMS,
|
|
|
+ zIndex: 3333,
|
|
|
+ __layerName: __flag,
|
|
|
+ })
|
|
|
+ state.map.addLayer(state.layerWMS)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const getBBOX = () => {
|
|
|
+ return `BBOX(location, ${state.map.getView().calculateExtent(state.map.getSize()).join(',')})`;
|
|
|
+ };
|
|
|
+ const initWebSocket = () => {
|
|
|
+ if (!state.ws.instance) {
|
|
|
+ state.ws.instance = new WebSocket(`ws://${location.host}/rh-ws-api/webSocket`)
|
|
|
+ state.ws.instance.onopen = (e) => {
|
|
|
+ const param = {
|
|
|
+ "cql": getBBOX(),
|
|
|
+ "realCql": null,
|
|
|
+ "userId": "18889231165"
|
|
|
+ }
|
|
|
+ state.ws.instance.send(JSON.stringify(param))
|
|
|
+ }
|
|
|
+ state.ws.instance.onmessage = (e) => {
|
|
|
+ try {
|
|
|
+ const json = JSON.parse(e.data)
|
|
|
+ const shipData = json.data
|
|
|
+ initShip(shipData)
|
|
|
+ } catch (e) {
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ const param = {
|
|
|
+ "cql": getBBOX(),
|
|
|
+ "realCql": null,
|
|
|
+ "userId": "18889231165"
|
|
|
+ }
|
|
|
+ if (state.ws.instance.readyState == 1) {
|
|
|
+ state.ws.instance.send(JSON.stringify(param))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const initShip = (data) => {
|
|
|
+ if (!state.ws.layerShip) {
|
|
|
+ state.ws.layerShip = new layer.Vector({
|
|
|
+ zIndex: 4444,
|
|
|
+ style: (f) => {
|
|
|
+ return MapStyle.ShipNormalStyle({
|
|
|
+ course: f.get('_course'),
|
|
|
+ speed: f.get('_speed'),
|
|
|
+ head: f.get('_head'),
|
|
|
+ mergeType: f.get('_mergeType'),
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ state.map.addLayer(state.ws.layerShip)
|
|
|
+ }
|
|
|
+ // 动态拼接数据的唯一标识DATA,不可修改
|
|
|
+ const features = data.map(v => {
|
|
|
+ try {
|
|
|
+ const feat: any = new format.WKT().readFeature(v.location)
|
|
|
+ feat.set('_course', v.targetCourse || 0)
|
|
|
+ feat.set('_speed', v.targetSpeed || 0)
|
|
|
+ feat.set('_head', v.targetHeading)
|
|
|
+ feat.set('_mergeType', v.mergeType)
|
|
|
+ feat.set('_data', v)
|
|
|
+ return feat
|
|
|
+ } catch (e) {
|
|
|
+ console.log(e)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ const vectorSource = new source.Vector({
|
|
|
+ features: features,
|
|
|
+ wrapX: false
|
|
|
+ });
|
|
|
+ state.ws.layerShip.setSource(vectorSource)
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ ...toRefs(state),
|
|
|
+ initMap,
|
|
|
+ }
|
|
|
+})
|