@@ -183,7 +184,7 @@ import { useRoute, useRouter } from 'vue-router'
import { urlParamsHandler, overwriteUrl } from '@/utils/tools'
import axios from 'axios'
import { api } from '@/utils/api'
-import { h3ToGeoBoundary } from 'h3-js'
+import { h3ToGeo, h3ToGeoBoundary } from 'h3-js'
export default {
name: 'Location',
@@ -201,6 +202,7 @@ export default {
methods: {
valueToRangeValue,
async initMap () {
+ console.info(h3ToGeo('8931aa42cb7ffff'))
const _this = this
const map = new maplibregl.Map({
container: 'analysisMap',
@@ -234,6 +236,7 @@ export default {
map.on('load', async function () {
console.info('map loaded')
/* 地图色块 */
+ _this.updateBoundaryBox()
const hexagonData = await _this.queryHexagon()
// 将查到的h3hexagon数据转为geojson
const polygonSourceData = _this.hexagonDataConverter(hexagonData)
@@ -257,12 +260,16 @@ export default {
/* 地图上的基站 */
const baseStationData = await _this.queryBaseStation()
+ _this.renderMarker(baseStationData, _this.tooltipType.baseStation)
+
/* 地图上的人 */
+ const mapFollowedSubscriberData = await _this.queryMapFollowedSubscriber()
+ _this.renderMarker(mapFollowedSubscriberData, _this.tooltipType.human)
/* 右侧关注列表 */
/* 右上角折线图 */
- _this.renderActiveSubscribersLine()
+ await _this.renderActiveSubscribersLine()
})
},
async renderDensityPie () {
@@ -272,7 +279,7 @@ export default {
this.loading.pieLoading = true
try {
const response = await axios.get(api.location.density, { params })
- const densityData = response.data.data.list
+ const densityData = response.data.data
// 按值的大小分为5组,并计算各组数量和颜色
this.pieValueRamp = this.calculateValueRamp(densityData)
const option = _.cloneDeep(pieOption)
@@ -301,15 +308,15 @@ export default {
}
this.loading.lineLoading = true
try {
- const curCountResponse = await axios.get(api.location.count, { ...params, cycle: 0, data: { cycle: 0 } })// 当前周期活跃用户总数
- const preCountResponse = await axios.get(api.location.count, { ...params, cycle: 1, data: { cycle: 1 } })// 上一周期活跃用户总数
+ const curCountResponse = await axios.get(api.location.count, { params: { ...params, cycle: 0 } })// 当前周期活跃用户总数
+ const preCountResponse = await axios.get(api.location.count, { params: { ...params, cycle: 1 } })// 上一周期活跃用户总数
this.activeCount = curCountResponse.data.data.total
const preActiveCount = preCountResponse.data.data.total
if (preActiveCount !== 0) {
- this.activeCountChain = (this.activeCount - preActiveCount) / preActiveCount
+ this.activeCountChain = preActiveCount !== '0' ? (this.activeCount - preActiveCount) / preActiveCount : ''
}
const trendResponse = await axios.get(api.location.trend, { params })
- const activeSubscribersData = trendResponse.data.data.result.values
+ const activeSubscribersData = trendResponse.data.data.result
const option = _.cloneDeep(appListChartOption)
option.series[0].data = activeSubscribersData.map(d => {
return [d[0], d[1], unitTypes.number]
@@ -334,7 +341,7 @@ export default {
this.loading.hexagonLoading = true
try {
const response = await axios.get(api.location.map, { params })
- return response.data.data.list
+ return response.data.data
} catch (e) {
this.errorMsgHandler(e)
console.error(e)
@@ -346,8 +353,34 @@ export default {
async queryBaseStation () {
this.loading.baseStationLoading = true
try {
- const response = await axios.get(api.location.baseStation)
- return response.data.data.list
+ // const response = await axios.get(api.location.baseStation)
+ const response = [
+ {
+ longitude: 116.38,
+ latitude: 39.9
+ },
+ {
+ longitude: 116.39,
+ latitude: 39.9
+ },
+ {
+ longitude: 116.383,
+ latitude: 39.886
+ },
+ {
+ longitude: 116.378,
+ latitude: 39.902
+ },
+ {
+ longitude: 116.369,
+ latitude: 39.91
+ },
+ {
+ longitude: 116.38,
+ latitude: 39.91
+ }
+ ]
+ return response // response.data.data.list
} catch (e) {
this.errorMsgHandler(e)
console.error(e)
@@ -356,9 +389,76 @@ export default {
}
return []
},
+ async queryMapFollowedSubscriber () {
+ this.loading.timeBarLoading = true
+ console.info(this.timeFilter)
+ console.info(this.minuteTimeFilter)
+ try {
+ const response = await axios.get(api.location.followedSubscriber, { params: this.minuteTimeFilter })
+ return response.data.data.list
+ } catch (e) {
+ this.errorMsgHandler(e)
+ console.error(e)
+ } finally {
+ this.loading.timeBarLoading = false
+ }
+ return []
+ },
+ renderMarker (data, type) {
+ let svg
+ if (type === this.tooltipType.baseStation) {
+ svg = '
'
+ } else if (type === this.tooltipType.human) {
+ svg = '
'
+ }
+ data.forEach(marker => {
+ const el = document.createElement('div')
+ el.className = `map-marker map-marker--${type}`
+ el.innerHTML = svg
+ // 鼠标事件,控制tooltip显示和marker尺寸
+ el.addEventListener('mouseenter', e => {
+ this.markerDom = el
+ if (!this.tooltip.mouseInMarkerOrTooltip) {
+ this.tooltip.x = e.clientX + 15 - e.offsetX
+ this.tooltip.y = e.clientY + 15 - e.offsetY
+ }
+ this.tooltip.mouseInMarkerOrTooltip = true
+ this.tooltip.type = this.tooltipType.baseStation
+ this.tooltip.showMarkerTooltip = true
+ el.classList.add('map-marker--hover')
+ })
+ el.addEventListener('mouseleave', event => {
+ const tooltipDom = document.getElementById('tooltip')
+ if (!tooltipDom.contains(event.relatedTarget)) {
+ el.classList.remove('map-marker--hover')
+ this.tooltip.mouseInMarkerOrTooltip = false
+ this.tooltip.showMarkerTooltip = false
+ }
+ })
+
+ new maplibregl.Marker({ element: el })
+ .setLngLat([marker.longitude, marker.latitude])
+ .addTo(this.mapChart)
+ })
+ },
+ updateBoundaryBox () {
+ const boundaryBox = this.mapChart.getBounds()
+ /*this.boundaryBox = {
+ maxLongitude: boundaryBox.getEast(),
+ maxLatitude: boundaryBox.getNorth(),
+ minLongitude: boundaryBox.getWest(),
+ minLatitude: boundaryBox.getSouth()
+ }*/
+ this.boundaryBox = {
+ maxLongitude: 140,
+ maxLatitude: 50,
+ minLongitude: 100,
+ minLatitude: 30
+ }
+ },
// 先使用min=0的等宽分组法,若后续出现特大或特小的异常值导致等宽分组效果不理想,考虑用分位数分组法
calculateValueRamp (data) {
- const max = _.maxBy(data, d => d.number)
+ const max = _.maxBy(data, d => Number(d.number))
const maxLength = String(max.number).length
const maxLegend = Math.ceil(max.number / Math.pow(10, maxLength - 1)) * Math.pow(10, maxLength - 1)
const result = []
@@ -395,7 +495,7 @@ export default {
}
},
getHexagonFillColor (number) {
- const ramp = this.pieValueRamp.filter(r => number >= r.start && number < r.end)
+ const ramp = this.pieValueRamp.filter(r => Number(number) >= r.start && Number(number) <= r.end)
if (ramp.length > 0) {
return ramp[0].color.split(',').map(n => Number(n))
}
@@ -413,7 +513,7 @@ export default {
hoverTrigger('hexGrid', _this.currentPolygon.id, false)
})
this.mapChart.on('mousemove', 'hexagon', ({ point, originalEvent, features }) => {
- if (!_this.tooltip.mouseIsInMarker) {
+ if (!_this.tooltip.mouseInMarkerOrTooltip) {
_this.tooltip.showPolygonTooltip = true
_this.tooltip.type = _this.tooltipType.hexagon
if (_this.tooltip.type === _this.tooltipType.hexagon && _this.currentPolygon.id && _this.currentPolygon.id !== features[0].id) {
@@ -434,10 +534,16 @@ export default {
}
},
tooltipMouseEnter () {
+ this.tooltip.mouseInMarkerOrTooltip = true
},
tooltipMouseMove () {
},
- tooltipMouseLeave () {
+ tooltipMouseLeave (event) {
+ if (this.markerDom && !this.markerDom.contains(event.relatedTarget)) {
+ this.tooltip.mouseInMarkerOrTooltip = false
+ this.tooltip.showMarkerTooltip = false
+ this.markerDom.classList.remove('map-marker--hover')
+ }
},
reload (startTime, endTime, dateRangeValue) {
this.timeFilter = { startTime: getSecond(startTime), endTime: getSecond(endTime), dateRangeValue: dateRangeValue }
@@ -467,6 +573,9 @@ export default {
}
},
watch: {
+ activeTab (n) {
+
+ }
},
computed: {
tooltipHeaderColor () {
@@ -520,7 +629,7 @@ export default {
timeFilter.value.startTime = parseInt(startTimeParam)
timeFilter.value.endTime = parseInt(endTimeParam)
}
- const minuteTimeFilter = ref({ startTime: timeFilter.value.startTime - 60, endTime: timeFilter.value.endTime })
+ const minuteTimeFilter = ref({ startTime: timeFilter.value.endTime - 60, endTime: timeFilter.value.endTime })
const tooltip = ref({
type: ''
})
@@ -556,6 +665,7 @@ export default {
pieValueRamp, // 饼图数值坡度,动态获取
boundaryBox, // 查六边形的范围,minLongitude、maxLongitude、minLatitude、maxLatitude
mapChart, // 地图对象
+ markerDom: shallowRef(null), // 记录当前鼠标悬停的marker的dom
pieChart, // 饼图对象
pieOption,
lineChart, // 折线图对象
@@ -643,17 +753,41 @@ export default {
border-radius: 50%;
cursor: default;
padding: 0;
+ transition: height .1s linear, width .1s linear;
+
+ svg {
+ transition: height .1s linear, width .1s linear;
+ }
&.map-marker--human {
background-color: #233447;
+
+ svg {
+ width: 14px;
+ height: 14px;
+ }
}
&.map-marker--base-station {
background-color: #585B5F;
+
+ svg {
+ width: 12px;
+ height: 12px;
+ }
}
&.map-marker--hover {
width: 36px;
height: 36px;
border: 2px solid rgba(255,255,255,1);
+
+ &.map-marker--human svg {
+ width: 23px;
+ height: 23px;
+ }
+ &.map-marker--base-station svg {
+ width: 20px;
+ height: 20px;
+ }
}
}
}