mirror of
https://github.com/dataease/dataease.git
synced 2025-02-24 19:42:56 +08:00
refactor(图表): 地图自定义区域支持轮播
This commit is contained in:
parent
341cb62097
commit
71f315d30e
1
core/core-frontend/src/models/chart/map.d.ts
vendored
1
core/core-frontend/src/models/chart/map.d.ts
vendored
@ -14,4 +14,5 @@ interface CustomGeoArea {
|
||||
type CustomGeoSubArea = CustomGeoArea & {
|
||||
geoAreaId: string
|
||||
scope: string
|
||||
scopeArr?: string[]
|
||||
}
|
||||
|
@ -63,15 +63,48 @@ export class BubbleMap extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
chart.container = container
|
||||
let geoJson = {} as FeatureCollection
|
||||
let customSubArea: CustomGeoSubArea[] = []
|
||||
if (areaId.startsWith('custom_') || scope) {
|
||||
let data = chart.data?.data
|
||||
if (areaId.startsWith('custom_')) {
|
||||
customSubArea = (await getCustomGeoArea(areaId)).data || []
|
||||
customSubArea.forEach(a => (a.scopeArr = a.scope?.split(',') || []))
|
||||
geoJson = cloneDeep(await getGeoJsonFile('156'))
|
||||
if (scope) {
|
||||
geoJson.features = geoJson.features.filter(f => scope.includes('156' + f.properties.adcode))
|
||||
}
|
||||
const areaNameMap = geoJson.features.reduce((p, n) => {
|
||||
p['156' + n.properties.adcode] = n.properties.name
|
||||
return p
|
||||
}, {})
|
||||
const { areaMapping } = parseJson(chart.senior)
|
||||
const areaMap = customSubArea.reduce((p, n) => {
|
||||
const mappedName = areaMapping?.[areaId]?.[n.name]
|
||||
if (mappedName) {
|
||||
n.name = mappedName
|
||||
}
|
||||
p[n.name] = n
|
||||
n.scopeArr = n.scope?.split(',') || []
|
||||
return p
|
||||
}, {})
|
||||
const fakeData = []
|
||||
data?.forEach(d => {
|
||||
const area = areaMap[d.name]
|
||||
if (area) {
|
||||
area.scopeArr.forEach(adcode => {
|
||||
fakeData.push({
|
||||
...d,
|
||||
name: areaNameMap[adcode],
|
||||
field: areaNameMap[adcode],
|
||||
scope: area.scopeArr,
|
||||
areaName: d.name
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
data = fakeData
|
||||
} else {
|
||||
geoJson = cloneDeep(await getGeoJsonFile(areaId))
|
||||
if (scope) {
|
||||
geoJson = cloneDeep(await getGeoJsonFile('156'))
|
||||
geoJson.features = geoJson.features.filter(f => scope.includes('156' + f.properties.adcode))
|
||||
} else {
|
||||
geoJson = cloneDeep(await getGeoJsonFile(areaId))
|
||||
}
|
||||
}
|
||||
let options: ChoroplethOptions = {
|
||||
preserveDrawingBuffer: true,
|
||||
@ -83,7 +116,7 @@ export class BubbleMap extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
type: 'geojson'
|
||||
},
|
||||
source: {
|
||||
data: chart.data?.data || [],
|
||||
data: data || [],
|
||||
joinBy: {
|
||||
sourceField: 'name',
|
||||
geoField: 'name',
|
||||
@ -164,7 +197,7 @@ export class BubbleMap extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
})
|
||||
dotLayer.once('loaded', () => {
|
||||
chart.container = container
|
||||
configCarouselTooltip(chart, view, chart.data?.data || [], null)
|
||||
configCarouselTooltip(chart, view, data || [], null, customSubArea, drawOption)
|
||||
})
|
||||
})
|
||||
return view
|
||||
@ -239,6 +272,8 @@ export class BubbleMap extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
features: areaJsonArr
|
||||
}
|
||||
const center = centroid(areaJson)
|
||||
// 轮播用
|
||||
area.centroid = [center.geometry.coordinates[0], center.geometry.coordinates[1]]
|
||||
dotData.push({
|
||||
name: area.name,
|
||||
size: d.value,
|
||||
|
@ -235,7 +235,7 @@ export class Map extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
})
|
||||
})
|
||||
chart.container = container
|
||||
configCarouselTooltip(chart, view, data, null)
|
||||
configCarouselTooltip(chart, view, data, null, customSubArea, drawOption)
|
||||
})
|
||||
return view
|
||||
}
|
||||
@ -455,31 +455,38 @@ export class Map extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
const customAttr = parseJson(chart.customAttr)
|
||||
const { label } = customAttr
|
||||
const data = chart.data.data
|
||||
const areaMap = data.reduce((obj, value) => {
|
||||
const areaMap = data?.reduce((obj, value) => {
|
||||
obj[value['field']] = value
|
||||
return obj
|
||||
}, {})
|
||||
const geoJsonMap = geoJson.features.reduce((p, n) => {
|
||||
if (n.properties['adcode']) {
|
||||
p['156' + n.properties['adcode']] = n
|
||||
}
|
||||
return p
|
||||
}, {})
|
||||
customSubArea.forEach(area => {
|
||||
const areaJsonArr = []
|
||||
area.scopeArr?.forEach(adcode => {
|
||||
const json = geoJsonMap[adcode]
|
||||
json && areaJsonArr.push(json)
|
||||
})
|
||||
if (areaJsonArr.length) {
|
||||
const areaJson: FeatureCollection = {
|
||||
type: 'FeatureCollection',
|
||||
features: areaJsonArr
|
||||
}
|
||||
const center = centroid(areaJson)
|
||||
// 轮播用
|
||||
area.centroid = [center.geometry.coordinates[0], center.geometry.coordinates[1]]
|
||||
}
|
||||
})
|
||||
//处理label
|
||||
options.label = false
|
||||
if (label.show) {
|
||||
const geoJsonMap = geoJson.features.reduce((p, n) => {
|
||||
if (n.properties['adcode']) {
|
||||
p['156' + n.properties['adcode']] = n
|
||||
}
|
||||
return p
|
||||
}, {})
|
||||
const labelLocation = []
|
||||
customSubArea.forEach(area => {
|
||||
const areaJsonArr = []
|
||||
area.scopeArr?.forEach(adcode => {
|
||||
const json = geoJsonMap[adcode]
|
||||
json && areaJsonArr.push(json)
|
||||
})
|
||||
if (areaJsonArr.length) {
|
||||
const areaJson: FeatureCollection = {
|
||||
type: 'FeatureCollection',
|
||||
features: areaJsonArr
|
||||
}
|
||||
if (area.centroid) {
|
||||
const content = []
|
||||
if (label.showDimension) {
|
||||
content.push(area.name)
|
||||
@ -488,11 +495,10 @@ export class Map extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
areaMap[area.name] &&
|
||||
content.push(valueFormatter(areaMap[area.name].value, label.quotaLabelFormatter))
|
||||
}
|
||||
const center = centroid(areaJson)
|
||||
labelLocation.push({
|
||||
name: content.join('\n\n'),
|
||||
x: center.geometry.coordinates[0],
|
||||
y: center.geometry.coordinates[1]
|
||||
x: area.centroid[0],
|
||||
y: area.centroid[1]
|
||||
})
|
||||
}
|
||||
})
|
||||
|
@ -6,13 +6,17 @@ import { parseJson } from '@/views/chart/components/js/util'
|
||||
import { Scene } from '@antv/l7-scene'
|
||||
import { deepCopy } from '@/utils/utils'
|
||||
|
||||
export const configCarouselTooltip = (chart, view, data, scene) => {
|
||||
export const configCarouselTooltip = (chart, view, data, scene, customSubArea, drawOption?) => {
|
||||
if (['bubble-map', 'map'].includes(chart.type)) {
|
||||
data = view.source.data.dataArray
|
||||
?.filter(i => i.dimensionList?.length > 0)
|
||||
.reduce((acc, current) => {
|
||||
const existingItem = acc.find(obj => {
|
||||
return obj.name === current.name || (obj.adcode && obj.adcode === current.adcode)
|
||||
if (drawOption?.areaId?.startsWith('custom_')) {
|
||||
return obj.areaName === current.areaName
|
||||
} else {
|
||||
return obj.name === current.name || (obj.adcode && obj.adcode === current.adcode)
|
||||
}
|
||||
})
|
||||
if (!existingItem) {
|
||||
acc.push(current)
|
||||
@ -22,9 +26,9 @@ export const configCarouselTooltip = (chart, view, data, scene) => {
|
||||
}
|
||||
if (carouselManagerInstances[chart.container]) {
|
||||
const instances = carouselManagerInstances[chart.container]
|
||||
instances.update(scene, chart, view, data)
|
||||
instances.update(scene, chart, view, data, customSubArea, drawOption)
|
||||
} else {
|
||||
new CarouselManager(scene, chart, view, data)
|
||||
new CarouselManager(scene, chart, view, data, customSubArea, drawOption)
|
||||
}
|
||||
}
|
||||
export const carouselManagerInstances: { [key: string]: CarouselManager } = {}
|
||||
@ -81,18 +85,30 @@ export class CarouselManager {
|
||||
*/
|
||||
private popup: Popup
|
||||
|
||||
/**
|
||||
* 自定义区域列表
|
||||
* @private
|
||||
*/
|
||||
private customSubArea: CustomGeoSubArea[]
|
||||
|
||||
/**
|
||||
* 渲染参数
|
||||
* @private
|
||||
*/
|
||||
private drawOption: L7PlotDrawOptions
|
||||
|
||||
// 保存事件监听函数的引用
|
||||
private onMouseEnterHandler: () => void
|
||||
private onMouseLeaveHandler: () => void
|
||||
private onVisibilityChangeHandler: () => void
|
||||
|
||||
constructor(scene, chart, view, data: any[]) {
|
||||
constructor(scene, chart, view, data: any[], customSubArea, drawOption?) {
|
||||
// 绑定事件处理函数
|
||||
this.onMouseEnterHandler = this.pauseCarouselPopups.bind(this)
|
||||
this.onMouseLeaveHandler = this.resumeCarouselPopups.bind(this)
|
||||
this.onVisibilityChangeHandler = this.handleVisibilityChange.bind(this)
|
||||
this.clearExistingTimers = this.clearExistingTimers.bind(this)
|
||||
this.init(scene, chart, view, data)
|
||||
this.init(scene, chart, view, data, customSubArea, drawOption)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -101,9 +117,10 @@ export class CarouselManager {
|
||||
* @param chart
|
||||
* @param view
|
||||
* @param data
|
||||
* @param customSubArea
|
||||
*/
|
||||
public update(scene, chart, view, data: any[]) {
|
||||
this.init(scene, chart, view, data)
|
||||
public update(scene, chart, view, data: any[], customSubArea, drawOption?) {
|
||||
this.init(scene, chart, view, data, customSubArea, drawOption)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -114,13 +131,15 @@ export class CarouselManager {
|
||||
* @param data
|
||||
* @private
|
||||
*/
|
||||
private init(scene, chart, view, data: any[]) {
|
||||
private init(scene, chart, view, data: any[], customSubArea, drawOption?) {
|
||||
this.view = view
|
||||
this.chart = chart
|
||||
this.scene = scene
|
||||
this.data = data
|
||||
this.popup = null
|
||||
this.currentIndex = 0
|
||||
this.customSubArea = customSubArea
|
||||
this.drawOption = drawOption
|
||||
this.clearPreviousInstance(this.chart.container)
|
||||
if (
|
||||
this.chart.customAttr?.tooltip?.show &&
|
||||
@ -336,6 +355,23 @@ export class CarouselManager {
|
||||
}
|
||||
|
||||
private getActiveData(index): any {
|
||||
if (this.drawOption?.areaId?.startsWith('custom_')) {
|
||||
const result = {
|
||||
type: 'FeatureCollection',
|
||||
features: []
|
||||
}
|
||||
const area = this.customSubArea.find(a => a.name === this.data[index].areaName)
|
||||
const areaMap = this.view.currentDistrictData.features.reduce((p, n) => {
|
||||
p['156' + n.properties.adcode] = n
|
||||
return p
|
||||
}, {})
|
||||
area?.scopeArr?.forEach(s => {
|
||||
if (areaMap[s]) {
|
||||
result.features.push(areaMap[s])
|
||||
}
|
||||
})
|
||||
return result
|
||||
}
|
||||
return {
|
||||
type: 'FeatureCollection',
|
||||
features: [
|
||||
@ -352,11 +388,21 @@ export class CarouselManager {
|
||||
* @private
|
||||
*/
|
||||
private getPopupData(index: number): any {
|
||||
return {
|
||||
data: this.data[index],
|
||||
centroid: this.view.currentDistrictData.features.find(
|
||||
i => i.properties.name === this.data[index].name
|
||||
)?.properties.centroid
|
||||
if (this.drawOption?.areaId?.startsWith('custom_')) {
|
||||
const data = this.data[index]
|
||||
const area = this.customSubArea?.find(a => a.name === data.areaName)
|
||||
data.name = data.areaName
|
||||
return {
|
||||
data,
|
||||
centroid: area.centroid
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
data: this.data[index],
|
||||
centroid: this.view.currentDistrictData.features.find(
|
||||
i => i.properties.name === this.data[index].name
|
||||
)?.properties.centroid
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user