CN-1484 feat: 地图事件开发

This commit is contained in:
chenjinsong
2023-12-01 17:22:32 +08:00
parent 8bbebc3a8b
commit 60d06792b4
4 changed files with 254 additions and 118 deletions

View File

@@ -23,9 +23,47 @@
.subscriber-map {
height: 100%;
width: 100%;
.maplibregl-canvas:focus-visible {
outline: none;
}
}
.panel-chart__no-data {
height: calc(100% - 46px);
}
}
.subscriber-map-point-tooltip {
position: fixed;
background-color: white;
width: 200px;
border: 1px solid #C5C5C5;
box-shadow: -1px 1px 10px -1px rgba(205,205,205,0.85);
border-radius: 2px;
.subscriber-map-point-tooltip__time {
padding: 10px;
font-size: 12px;
color: #353636;
font-weight: bold;
}
.subscriber-map-point-tooltip__coordinates {
padding: 0 10px 10px;
.subscriber-map-point-tooltip__coordinate {
display: flex;
.coordinate__label {
width: 115px;
font-size: 12px;
color: #575757;
}
.coordinate__value {
font-size: 12px;
color: #353636;
font-weight: bold;
}
}
}
}
}

View File

@@ -98,7 +98,7 @@ export const entityType = {
app: 'app',
domain: 'domain',
ip: 'ip',
subscribe: 'subscribe'
subscriber: 'subscriber'
}
export const knowledgeCardUpdateRecordType = {
@@ -153,7 +153,7 @@ export const entityDetailTabConfig = [
]
},
{
name: 'subscribe',
name: 'subscriber',
config: [
{ name: entityDetailTabsName.deviceInformation, label: 'entities.deviceInformation', icon: 'cn-icon cn-icon-device-info', tag: 0 },
{ name: entityDetailTabsName.accountInformation, label: 'entities.accountInformation', icon: 'cn-icon cn-icon-account-info', tag: 0 },

View File

@@ -17,6 +17,21 @@
<chart-error v-if="showError" :content="errorMsg" />
<div id="subscriberMap" class="subscriber-map"></div>
</div>
<!-- 地图point悬浮框 -->
<div class="subscriber-map-point-tooltip" v-if="tooltip.showTooltip" :style="{'left': `${tooltip.x}px`, 'top': `${tooltip.y}px`}">
<div class="subscriber-map-point-tooltip__time">{{dateFormatByAppearance(currentPoint.stat_time)}}</div>
<div class="subscriber-map-point-tooltip__coordinates">
<div class="subscriber-map-point-tooltip__coordinate">
<div class="coordinate__label">{{$t('overall.longitude')}}</div>
<div class="coordinate__value">{{currentPoint.longitude}}</div>
</div>
<div class="subscriber-map-point-tooltip__coordinate">
<div class="coordinate__label">{{$t('overall.latitude')}}</div>
<div class="coordinate__value">{{currentPoint.latitude}}</div>
</div>
</div>
</div>
</div>
</template>
@@ -28,9 +43,10 @@ import maplibregl from 'maplibre-gl'
import mapStyle from './mapStyle'
import axios from 'axios'
import { api } from '@/utils/api'
import 'maplibre-gl/dist/maplibre-gl.css'
import _ from 'lodash'
import { ref } from 'vue'
import { getNowTime } from '@/utils/date-util'
import { getNowTime, getSecond } from '@/utils/date-util'
export default {
name: 'EntityDetailMap',
@@ -39,22 +55,19 @@ export default {
ChartError,
ChartNoData
},
data () {
return {
}
},
mounted () {
this.initMap()
},
methods: {
initMap () {
async initMap () {
const _this = this
const map = new maplibregl.Map({
container: 'subscriberMap',
style: mapStyle,
center: [116.39, 39.9],
zoom: 9,
maxZoom: 12,
minZoom: 4,
center: this.center,
maxZoom: this.maxZoom,
minZoom: this.minZoom,
zoom: 7,
transformRequest: function (url, resourceType) {
if (resourceType === 'Tile' && url.indexOf('https://api.maptiler.com/tiles/v3') > -1) {
const urlParams = url.split('.pbf')[0].split('/')
@@ -85,52 +98,102 @@ export default {
}
})
/* axios.get(`${api.entity.locationTrack}?resource=${this.entity.entityName}`).then(res => {
}) */
this.toggleLoading(false)
const res = {
status: 200,
data: {
data: {
result: [
{
stat_time: 1701259999,
subscriber_id: '883849',
subscriber_longitude: 116.29,
subscriber_latitude: 39.8
},
{
stat_time: 1701269999,
subscriber_id: '883849',
subscriber_longitude: 116.34,
subscriber_latitude: 39.85
},
{
stat_time: 1701279999,
subscriber_id: '883849',
subscriber_longitude: 116.29,
subscriber_latitude: 39.9
},
{
stat_time: 1701299999,
subscriber_id: '883849',
subscriber_longitude: 116.39,
subscriber_latitude: 39.9
},
{
stat_time: 1701289999,
subscriber_id: '883849',
subscriber_longitude: 116.3,
subscriber_latitude: 39.97
this.queryData().then(res => {
this.showError = false
const result = _.get(res, 'data.data.result', []).sort((a, b) => a.stat_time - b.stat_time)
const route = this.generateRouteGEOJSON(result)
const points = this.generatePointsGEOJSON(result)
map.on('load', () => {
map.jumpTo({ center: this.computeMapCenter(result) })
map.zoomTo(this.computeMapZoom(result))
map.loadImage(
`${window.location.protocol}//${window.location.host}/images/entity-detail/track-point.png`,
(error, image) => {
if (error) throw error
map.addImage('trace-point', image)
map.addSource('points', {
type: 'geojson',
data: points
})
map.addLayer(this.generatePointsLayer())
}
]
}
}
}
const result = _.get(res, 'data.data.result', []).sort((a, b) => a.stat_time - b.stat_time)
)
map.addSource('route', {
type: 'geojson',
lineMetrics: true,
data: route
})
map.addLayer(this.generateRouteLayer())
const route = {
this.myChart = map
// point的鼠标事件
map.on('mouseenter', 'points', () => {
_this.tooltip.showTooltip = true
})
map.on('mouseleave', 'points', () => {
_this.tooltip.showTooltip = false
})
map.on('mousemove', 'points', ({ point, originalEvent, features }) => {
_this.tooltip.x = originalEvent.clientX + 10
_this.tooltip.y = originalEvent.clientY - 95
_this.currentPoint = { ...features[0].properties }
})
})
}).catch(e => {
this.showError = true
console.error(e)
this.errorMsg = this.errorMsgHandler(e)
}).finally(() => {
this.toggleLoading(false)
})
},
queryData () {
return new Promise((resolve, reject) => {
resolve({
status: 200,
data: {
data: {
result: [
{
stat_time: 1701259999,
subscriber_id: '883849',
subscriber_longitude: 116.29,
subscriber_latitude: 39.8
},
{
stat_time: 1701269999,
subscriber_id: '883849',
subscriber_longitude: 116.34,
subscriber_latitude: 39.85
},
{
stat_time: 1701279999,
subscriber_id: '883849',
subscriber_longitude: 116.29,
subscriber_latitude: 39.9
},
{
stat_time: 1701299999,
subscriber_id: '883849',
subscriber_longitude: 116.39,
subscriber_latitude: 39.9
},
{
stat_time: 1701289999,
subscriber_id: '883849',
subscriber_longitude: 116.3,
subscriber_latitude: 39.97
}
]
}
}
})
})
// return axios.get(`${api.entity.locationTrack}?resource=${this.entity.entityName}`)
},
generateRouteGEOJSON (result) {
return {
type: 'FeatureCollection',
features: [
{
@@ -142,8 +205,9 @@ export default {
}
]
}
const points = {
},
generatePointsGEOJSON (result) {
return {
type: 'FeatureCollection',
features: result.map((r, index) => {
return {
@@ -154,68 +218,91 @@ export default {
},
properties: {
index: index + 1,
stat_time: r.stat_time
stat_time: r.stat_time,
longitude: r.subscriber_longitude,
latitude: r.subscriber_latitude
}
}
})
}
map.on('load', () => {
map.loadImage(
`${window.location.protocol}//${window.location.host}/images/entity-detail/track-point.png`,
(error, image) => {
if (error) throw error
map.addImage('trace-point', image)
map.addSource('points', {
type: 'geojson',
data: points
})
map.addLayer({
id: 'points',
type: 'symbol',
source: 'points',
layout: {
'icon-image': 'trace-point',
'icon-size': 0.7,
'icon-offset': [0, -20],
'text-field': ['get', 'index'],
'text-font': ['Noto Sans Bold'],
'text-offset': [0, -1.1],
'text-size': 13
},
paint: {
'text-color': '#FFF'
}
})
}
)
map.addSource('route', {
type: 'geojson',
lineMetrics: true,
data: route
})
map.addLayer({
id: 'route',
source: 'route',
type: 'line',
paint: {
'line-color': '#E26154',
'line-width': 4,
'line-gradient': [
'interpolate',
['linear'],
['line-progress'],
0,
'#F4B32F',
1,
'#E26154'
]
},
layout: {
'line-cap': 'round',
'line-join': 'round'
}
})
},
generateRouteLayer () {
return {
id: 'route',
source: 'route',
type: 'line',
paint: {
'line-color': '#E26154',
'line-width': 4,
'line-gradient': [
'interpolate',
['linear'],
['line-progress'],
0,
'#F4B32F',
1,
'#E26154'
]
},
layout: {
'line-cap': 'round',
'line-join': 'round'
}
}
},
generatePointsLayer () {
return {
id: 'points',
type: 'symbol',
source: 'points',
layout: {
'icon-image': 'trace-point',
'icon-size': 0.7,
'icon-offset': [0, -20],
'text-field': ['get', 'index'],
'text-font': ['Noto Sans Bold'],
'text-offset': [0, -1.1],
'text-size': 13
},
paint: {
'text-color': '#FFF'
}
}
},
computeMapCenter (result) {
const longitude = result.map(r => r.subscriber_longitude)
const latitude = result.map(r => r.subscriber_latitude)
return [
_.floor((_.max(longitude) + _.min(longitude)) / 2, 6),
_.floor((_.max(latitude) + _.min(latitude)) / 2, 6)
]
},
computeMapZoom (result) {
const longitude = result.map(r => r.subscriber_longitude)
const latitude = result.map(r => r.subscriber_latitude)
const longitudeRange = _.max(longitude) - _.min(longitude)
const latitudeRange = _.max(latitude) - _.min(latitude)
const max = _.max([this.minZoom, 7 - Math.log2(_.max([longitudeRange, latitudeRange]))])
return _.min([max, this.maxZoom])
},
reload (startTime, endTime, dateRangeValue) {
this.toggleLoading(true)
this.timeFilter = { startTime: getSecond(startTime), endTime: getSecond(endTime), dateRangeValue: dateRangeValue }
this.queryData().then(res => {
this.showError = false
const result = _.get(res, 'data.data.result', []).sort((a, b) => a.stat_time - b.stat_time)
const route = this.generateRouteGEOJSON(result)
const points = this.generatePointsGEOJSON(result)
this.myChart.getSource('route').setData(route)
this.myChart.getSource('points').setData(points)
this.myChart.jumpTo({ center: this.computeMapCenter(result) })
this.myChart.zoomTo(this.computeMapZoom(result))
}).catch(e => {
this.showError = true
console.error(e)
this.errorMsg = this.errorMsgHandler(e)
}).finally(() => {
this.toggleLoading(false)
})
}
},
@@ -225,8 +312,19 @@ export default {
const { startTime, endTime } = getNowTime(dateRangeValue)
timeFilter.value.startTime = startTime
timeFilter.value.endTime = endTime
const currentPoint = ref({})
const tooltip = ref({
showTooltip: false
})
return {
timeFilter
timeFilter,
currentPoint,
tooltip,
maxZoom: 11,
minZoom: 1,
center: [116.38, 39.9]
}
}
}

View File

@@ -39,7 +39,7 @@ export default {
entityData.appName = query.entityName
break
}
case 'subscribe': {
case 'subscriber': {
panelType = panelTypeAndRouteMapping.subscribeEntityDetail
entityData.appName = query.entityName
break