...
|
...
|
@@ -2,7 +2,7 @@ |
2
|
2
|
<!-- 原生方式,没有使用vue-echarts -->
|
3
|
3
|
<n-space vertical>
|
4
|
4
|
<n-spin :show="show">
|
5
|
|
- <div :style="`width:${w}px;height:${h}px;`" ref="map3DRef"></div>
|
|
5
|
+ <div id="map3DId" :style="`width:${w}px;height:${h}px;`"></div>
|
6
|
6
|
</n-spin>
|
7
|
7
|
</n-space>
|
8
|
8
|
</template>
|
...
|
...
|
@@ -12,7 +12,7 @@ import { onMounted, ref, nextTick, PropType, toRefs, watch, reactive } from 'vue |
12
|
12
|
import * as echarts from 'echarts'
|
13
|
13
|
import { registerMap } from 'echarts/core'
|
14
|
14
|
import 'echarts-gl'
|
15
|
|
-import config, { areaEnum } from './config'
|
|
15
|
+import config, { areaEnum, dataPointI, HistoryParentType } from './config'
|
16
|
16
|
import { getGeoJsonMap } from '@/api/external/common'
|
17
|
17
|
import dataMaps from './data.json'
|
18
|
18
|
|
...
|
...
|
@@ -29,8 +29,6 @@ const iconStr = ref( |
29
|
29
|
|
30
|
30
|
const { w, h } = toRefs(props.chartConfig.attr)
|
31
|
31
|
|
32
|
|
-const map3DRef = ref()
|
33
|
|
-
|
34
|
32
|
const show = ref(true)
|
35
|
33
|
|
36
|
34
|
const chartInstance = ref()
|
...
|
...
|
@@ -47,7 +45,7 @@ const toolBoxOption = ref({ |
47
|
45
|
iconStyle: {
|
48
|
46
|
color: ''
|
49
|
47
|
},
|
50
|
|
- onclick: () => watchAdcode()
|
|
48
|
+ onclick: () => mapClickBack()
|
51
|
49
|
}
|
52
|
50
|
}
|
53
|
51
|
})
|
...
|
...
|
@@ -60,44 +58,53 @@ watch( |
60
|
58
|
toolBoxOption.value.feature.myFullButton.iconStyle.color = iconColor
|
61
|
59
|
toolBoxOption.value.right = iconDistanceRight
|
62
|
60
|
toolBoxOption.value.top = iconDistanceTop
|
63
|
|
- },
|
64
|
|
- {
|
65
|
|
- deep: true
|
66
|
61
|
}
|
67
|
62
|
)
|
68
|
63
|
|
|
64
|
+//追加右上角返回图标配置
|
69
|
65
|
props.chartConfig.option = {
|
70
|
66
|
...props.chartConfig.option,
|
71
|
67
|
...{ toolbox: toolBoxOption.value }
|
72
|
68
|
}
|
73
|
69
|
|
74
|
70
|
//地图点击返回
|
75
|
|
-const watchAdcode = async () => {
|
76
|
|
- if (props.chartConfig.option.drillingIn) {
|
77
|
|
- //如果是从右边配置里设置的,比如点击四川省,然后点击返回
|
78
|
|
- const savePopParent = saveHistoryParent.value.pop()
|
79
|
|
- let saveAdcode: any = savePopParent?.adcode
|
80
|
|
- saveLevelStr.level = savePopParent?.level as string
|
81
|
|
- if (!savePopParent) {
|
82
|
|
- saveAdcode = getParentAdcode(props.chartConfig.option.mapRegion.adcode)
|
83
|
|
- saveLevelStr.level = (regionMapParentArea as any)[props.chartConfig.option.mapRegion.saveSelect.levelStr]
|
84
|
|
- }
|
85
|
|
- if (saveAdcode === 0) {
|
86
|
|
- saveAdcode = 'china'
|
87
|
|
- saveLevelStr.level = 'COUNTRY'
|
|
71
|
+const mapClickBack = async () => {
|
|
72
|
+ try {
|
|
73
|
+ if (props.chartConfig.option.drillingIn) {
|
|
74
|
+ //如果是从右边配置里设置的,比如点击四川省,然后点击返回
|
|
75
|
+ const savePopParent = saveHistoryParent.value.pop()
|
|
76
|
+ let saveAdcode = savePopParent?.adcode as string | number
|
|
77
|
+ saveLevelStr.level = savePopParent?.level
|
|
78
|
+ if (!savePopParent) {
|
|
79
|
+ saveAdcode = getParentAdcode(props.chartConfig.option.mapRegion.adcode)
|
|
80
|
+ saveLevelStr.level = (regionMapParentArea as Recordable)[props.chartConfig.option.mapRegion.saveSelect.levelStr]
|
|
81
|
+ }
|
|
82
|
+ if (saveAdcode === 0) {
|
|
83
|
+ saveAdcode = 'china'
|
|
84
|
+ saveLevelStr.level = 'COUNTRY'
|
|
85
|
+ }
|
|
86
|
+ await registerGeojson(saveAdcode)
|
|
87
|
+ const adcode = saveAdcode === 100000 ? 'china' : saveAdcode
|
|
88
|
+ setMap3DPartOption(adcode)
|
|
89
|
+ handleSetOption(chartInstance.value, props.chartConfig.option)
|
|
90
|
+ handleDataPoint(adcode)
|
88
|
91
|
}
|
89
|
|
- await getGeojson(saveAdcode)
|
90
|
|
- const adcode = saveAdcode === 100000 ? 'china' : saveAdcode
|
91
|
|
- props.chartConfig.option.geo3D.map = adcode
|
92
|
|
- props.chartConfig.option.series.forEach((item: any) => {
|
93
|
|
- if (item.type === 'map3D') item.map = adcode
|
94
|
|
- item.data = props.chartConfig.option.dataset
|
95
|
|
- })
|
96
|
|
- handleSetOption(chartInstance.value, props.chartConfig.option)
|
97
|
|
- handleDataPoint(adcode)
|
|
92
|
+ } catch (error) {
|
|
93
|
+ console.error('地图点击返回出错', error)
|
98
|
94
|
}
|
99
|
95
|
}
|
100
|
96
|
|
|
97
|
+//设置map3D部分属性
|
|
98
|
+const setMap3DPartOption = (adcode: number | string) => {
|
|
99
|
+ props.chartConfig.option.geo3D.map = adcode
|
|
100
|
+ props.chartConfig.option.series.forEach((item: Recordable) => {
|
|
101
|
+ if (item.type === 'map3D') {
|
|
102
|
+ item.map = adcode
|
|
103
|
+ item.data = props.chartConfig.option.dataset
|
|
104
|
+ }
|
|
105
|
+ })
|
|
106
|
+}
|
|
107
|
+
|
101
|
108
|
const regionMapParentArea = {
|
102
|
109
|
[areaEnum.PROVINCE]: areaEnum.COUNTRY, //省份的上一级 中国
|
103
|
110
|
[areaEnum.CITY]: areaEnum.PROVINCE, //城市的上一级 省份
|
...
|
...
|
@@ -105,62 +112,63 @@ const regionMapParentArea = { |
105
|
112
|
[areaEnum.TOWN]: areaEnum.COUNTY //镇的上一级 县或者区
|
106
|
113
|
}
|
107
|
114
|
|
108
|
|
-//地图点击
|
109
|
|
-const handleMap3DClick = async (params: any) => {
|
|
115
|
+//三维地图点击
|
|
116
|
+const handleMap3DClick = async (params: Recordable) => {
|
110
|
117
|
if (props.chartConfig.option.drillingIn) {
|
111
|
118
|
const { name } = params
|
112
|
|
- saveGeojson.value?.features.forEach((item: any) => {
|
|
119
|
+ saveGeojson.value?.features.forEach((item: Recordable) => {
|
113
|
120
|
if (item.properties.name === name) {
|
114
|
121
|
const level = item.properties.level.toUpperCase()
|
115
|
122
|
const adcode = item.properties.adcode
|
|
123
|
+ //如果是区则终止,目前没有加区下面的geojson数据
|
116
|
124
|
if (level === 'DISTRICT') return
|
117
|
|
- if(String(adcode).startsWith('15') && level===areaEnum.CITY) return
|
|
125
|
+ //特殊处理15开头的geojson数据
|
|
126
|
+ if (String(adcode).startsWith('15') && level === areaEnum.CITY) return
|
118
|
127
|
props.chartConfig.option.mapRegion.adcode = adcode
|
119
|
128
|
saveLevelStr.level = level
|
120
|
129
|
handleDataPoint(adcode)
|
121
|
130
|
saveHistoryParent.value.push({
|
122
|
131
|
adcode: item.properties.parent.adcode,
|
123
|
|
- level: (regionMapParentArea as any)[level]
|
|
132
|
+ level: (regionMapParentArea as Recordable)[level]
|
124
|
133
|
})
|
125
|
134
|
}
|
126
|
135
|
})
|
127
|
136
|
}
|
128
|
137
|
}
|
129
|
138
|
|
130
|
|
-const saveGeojson: any = ref({}) // 保存geojson
|
|
139
|
+// 保存geojson
|
|
140
|
+const saveGeojson: Recordable = ref({})
|
131
|
141
|
|
132
|
|
-const chinaDefaultRegionId = ref(100000) //如果是china则adcode为100000
|
|
142
|
+//如果是china则adcode为100000
|
|
143
|
+const chinaDefaultRegionId = ref(100000)
|
133
|
144
|
|
134
|
|
-const saveLevelStr = reactive({
|
135
|
|
- // 地区级别
|
136
|
|
- level: ''
|
|
145
|
+// 保存地区级别
|
|
146
|
+const saveLevelStr = reactive<{ level: string | undefined }>({
|
|
147
|
+ level: ''
|
137
|
148
|
})
|
138
|
149
|
|
139
|
|
-//父级地区编码和级别接口
|
140
|
|
-interface HistoryParentType {
|
141
|
|
- adcode: number
|
142
|
|
- level: string
|
143
|
|
-}
|
144
|
|
-
|
|
150
|
+// 保存上一级的adcode和行政级别
|
145
|
151
|
const saveHistoryParent = ref<HistoryParentType[]>([])
|
146
|
152
|
|
147
|
153
|
//动态注册地图
|
148
|
|
-const getGeojson = (regionId: any) => {
|
|
154
|
+const registerGeojson = (regionId: number | string) => {
|
149
|
155
|
try {
|
150
|
156
|
return new Promise<boolean>(resolve => {
|
151
|
|
- const { levelStr } = props.chartConfig.option.mapRegion.saveSelect //右侧配置项获取的行政级别
|
|
157
|
+ const { levelStr } = props.chartConfig.option.mapRegion.saveSelect //从右侧配置项获取的行政级别
|
152
|
158
|
getGeoJsonMap(
|
153
|
159
|
regionId === 'china' ? chinaDefaultRegionId.value : regionId,
|
154
|
160
|
!saveLevelStr.level ? levelStr : saveLevelStr.level
|
155
|
161
|
).then(res => {
|
156
|
|
- const { geoJson, name, code, level } = res.data
|
157
|
|
- const geoJsonFile = JSON.parse(geoJson)
|
158
|
|
- if (!geoJsonFile) return
|
159
|
|
- saveGeojson.value = geoJsonFile
|
160
|
|
- const nameChina = name === '中国' ? 'china' : name
|
161
|
|
- registerMap(level === areaEnum.COUNTRY ? nameChina : code, { geoJSON: geoJsonFile as any, specialAreas: {} })
|
162
|
|
- show.value = false
|
163
|
|
- resolve(true)
|
|
162
|
+ if (res.data) {
|
|
163
|
+ const { geoJson, name, code, level } = res.data
|
|
164
|
+ if (!geoJson) return
|
|
165
|
+ const geoJsonFile = JSON.parse(geoJson)
|
|
166
|
+ saveGeojson.value = geoJsonFile
|
|
167
|
+ const nameChina = name === '中国' ? 'china' : name
|
|
168
|
+ registerMap(level === areaEnum.COUNTRY ? nameChina : code, { geoJSON: geoJsonFile, specialAreas: {} })
|
|
169
|
+ resolve(true)
|
|
170
|
+ show.value = false
|
|
171
|
+ }
|
164
|
172
|
})
|
165
|
173
|
})
|
166
|
174
|
} catch (error) {
|
...
|
...
|
@@ -171,11 +179,13 @@ const getGeojson = (regionId: any) => { |
171
|
179
|
}
|
172
|
180
|
}
|
173
|
181
|
|
|
182
|
+//注册出错则注册空的,不然在选择正确的adcode,则视图无法更新
|
|
183
|
+registerMap(props.chartConfig.option.mapRegion.adcode, { geoJSON: {} as any, specialAreas: {} })
|
174
|
184
|
|
175
|
|
-//传adcode 获取上级
|
|
185
|
+//获取上级adcode
|
176
|
186
|
const getParentAdcode = (adcode: number) => {
|
177
|
187
|
let adcodeNum = 100000
|
178
|
|
- saveGeojson.value?.features.forEach((item: any) => {
|
|
188
|
+ saveGeojson.value?.features?.forEach((item: Recordable) => {
|
179
|
189
|
if (item.properties.adcode === adcode) {
|
180
|
190
|
adcodeNum = item.properties.parent.adcode
|
181
|
191
|
}
|
...
|
...
|
@@ -193,59 +203,64 @@ watch( |
193
|
203
|
}
|
194
|
204
|
)
|
195
|
205
|
|
196
|
|
-const initMap = async () => {
|
197
|
|
- chartInstance.value = echarts.init(map3DRef.value)
|
198
|
|
- await nextTick()
|
199
|
|
- await getGeojson(props.chartConfig.option.mapRegion.adcode)
|
200
|
|
- await nextTick().then(() => {
|
201
|
|
- handleSetOption(chartInstance.value, props.chartConfig.option)
|
202
|
|
- })
|
203
|
|
- chartInstance.value.on('click', (e: any) => {
|
204
|
|
- handleMap3DClick(e)
|
205
|
|
- })
|
|
206
|
+//初始化3D地图
|
|
207
|
+const initMap3D = async () => {
|
|
208
|
+ try {
|
|
209
|
+ const dom = document.getElementById('map3DId') as HTMLElement
|
|
210
|
+ chartInstance.value = echarts.init(dom)
|
|
211
|
+ await nextTick()
|
|
212
|
+ await registerGeojson(props.chartConfig.option.mapRegion.adcode)
|
|
213
|
+ await nextTick().then(() => {
|
|
214
|
+ handleSetOption(chartInstance.value, props.chartConfig.option)
|
|
215
|
+ })
|
|
216
|
+ //三维地图点击
|
|
217
|
+ chartInstance.value.on('click', (e: Recordable) => {
|
|
218
|
+ handleMap3DClick(e)
|
|
219
|
+ })
|
|
220
|
+ } catch (error) {
|
|
221
|
+ console.error('[initMap3D]初始化3d地图出错', error)
|
|
222
|
+ }
|
206
|
223
|
}
|
207
|
224
|
|
|
225
|
+onMounted(() => {
|
|
226
|
+ setTimeout(() => {
|
|
227
|
+ initMap3D()
|
|
228
|
+ }, 500)
|
|
229
|
+})
|
|
230
|
+
|
208
|
231
|
// 手动触发渲染
|
209
|
|
-const handleSetOption = (instance: any, option: any) => {
|
210
|
|
- if (!instance) return
|
|
232
|
+const handleSetOption = (instance: any, option: Recordable) => {
|
211
|
233
|
try {
|
|
234
|
+ if (!instance) return
|
212
|
235
|
instance.clear()
|
213
|
236
|
instance.setOption(option)
|
214
|
237
|
} catch (error) {
|
215
|
|
- console.error('触发渲染出错', error)
|
|
238
|
+ console.error('手动触发渲染出错', error)
|
216
|
239
|
}
|
217
|
240
|
}
|
218
|
241
|
|
219
|
|
-onMounted(() => {
|
220
|
|
- initMap()
|
221
|
|
-})
|
222
|
|
-
|
223
|
242
|
//处理数据标点
|
224
|
|
-const handleDataPoint = (newData: any) => {
|
|
243
|
+const handleDataPoint = (newData: string | number) => {
|
225
|
244
|
if (newData === 'china') {
|
|
245
|
+ //全国则显示所有标点
|
226
|
246
|
props.chartConfig.option.dataset = dataMaps
|
227
|
247
|
} else {
|
228
|
|
- props.chartConfig.option.dataset = dataMaps.filter((item: any) => item.adcode === newData)
|
|
248
|
+ //显示对应区域标点
|
|
249
|
+ props.chartConfig.option.dataset = dataMaps.filter((item: dataPointI) => item.adcode === newData)
|
229
|
250
|
}
|
230
|
251
|
}
|
231
|
252
|
|
232
|
253
|
//监听地图展示区域发生变化
|
233
|
254
|
watch(
|
234
|
255
|
() => `${props.chartConfig.option.mapRegion.adcode}`,
|
235
|
|
- async (newData: any) => {
|
|
256
|
+ async (newData: string | number) => {
|
236
|
257
|
try {
|
237
|
|
- await getGeojson(newData)
|
238
|
|
- props.chartConfig.option.geo3D.map = newData
|
239
|
|
- props.chartConfig.option.series.forEach((item: any) => {
|
240
|
|
- if (item.type === 'map3D') {
|
241
|
|
- item.map = newData
|
242
|
|
- item.data = props.chartConfig.option.dataset
|
243
|
|
- }
|
244
|
|
- })
|
|
258
|
+ await registerGeojson(newData)
|
|
259
|
+ setMap3DPartOption(newData)
|
245
|
260
|
handleSetOption(chartInstance.value, props.chartConfig.option)
|
246
|
261
|
handleDataPoint(newData)
|
247
|
262
|
} catch (error) {
|
248
|
|
- console.log('展示区域发生变化出错', error)
|
|
263
|
+ console.log('监听地图展示区域发生变化', error)
|
249
|
264
|
}
|
250
|
265
|
},
|
251
|
266
|
{
|
...
|
...
|
@@ -260,7 +275,7 @@ watch( |
260
|
275
|
try {
|
261
|
276
|
handleSetOption(chartInstance.value, newData)
|
262
|
277
|
} catch (error) {
|
263
|
|
- console.log(error)
|
|
278
|
+ console.log('监听地图右侧配置项变化', error)
|
264
|
279
|
}
|
265
|
280
|
},
|
266
|
281
|
{
|
...
|
...
|
@@ -273,14 +288,14 @@ watch( |
273
|
288
|
() => props.chartConfig.option.dataset,
|
274
|
289
|
newData => {
|
275
|
290
|
try {
|
276
|
|
- props.chartConfig.option.series.forEach((item: any) => {
|
|
291
|
+ props.chartConfig.option.series.forEach((item: Recordable) => {
|
277
|
292
|
if (item.type === 'map3D') {
|
278
|
293
|
item.data = newData
|
279
|
294
|
}
|
280
|
295
|
})
|
281
|
296
|
handleSetOption(chartInstance.value, props.chartConfig.option)
|
282
|
297
|
} catch (error) {
|
283
|
|
- console.log(error)
|
|
298
|
+ console.log('监听地图dataset配置项变化', error)
|
284
|
299
|
}
|
285
|
300
|
},
|
286
|
301
|
{
|
...
|
...
|
|