123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- <template>
- <div class="visitor-trend">
- <div ref="chartRef" style="width: 100%; min-height: 300px"></div>
- <div style="position: absolute; top: 20px; right: 0">
- <el-select v-model="selectedCountry" style="width: 160px" @change="initChart">
- <el-option v-for="item in countryOptions" :key="item.value" :label="item.label" :value="item.value" />
- </el-select>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { ref, onMounted, onUnmounted } from 'vue';
- import * as echarts from 'echarts/core';
- import { MapChart } from 'echarts/charts';
- import { TooltipComponent, GeoComponent } from 'echarts/components';
- import { CanvasRenderer } from 'echarts/renderers';
- echarts.use([MapChart, TooltipComponent, GeoComponent, CanvasRenderer]);
- const chartRef = ref<HTMLElement | null>(null);
- let chartInstance: echarts.ECharts | null = null;
- const countryOptions = [
- { value: 'world', label: '世界' },
- { value: 'usa', label: '美国' },
- { value: 'china', label: '中国' },
- { value: 'vietnam', label: '越南' },
- { value: 'thailand', label: '泰国' },
- { value: 'malaysia', label: '马来西亚' },
- { value: 'singapore', label: '新加坡' },
- { value: 'indonesia', label: '印度尼西亚' },
- { value: 'philippines', label: '菲律宾' },
- { value: 'cambodia', label: '柬埔寨' },
- { value: 'laos', label: '老挝' },
- { value: 'myanmar', label: '缅甸' },
- { value: 'brunei', label: '文莱' },
- ];
- const selectedCountry = ref('world');
- // 动态 import 映射
- const countryImportMap: Record<string, () => Promise<any>> = {
- world: () => import('echarts-countries-js/echarts-countries-js/world.js'),
- usa: () => import('echarts-countries-js/echarts-countries-js/USA.js'),
- china: () => import('echarts-countries-js/echarts-countries-js/China.js'),
- vietnam: () => import('echarts-countries-js/echarts-countries-js/Vietnam.js'),
- thailand: () => import('echarts-countries-js/echarts-countries-js/Thailand.js'),
- malaysia: () => import('echarts-countries-js/echarts-countries-js/Malaysia.js'),
- singapore: () => import('echarts-countries-js/echarts-countries-js/Singapore.js'),
- indonesia: () => import('echarts-countries-js/echarts-countries-js/Indonesia.js'),
- philippines: () => import('echarts-countries-js/echarts-countries-js/Philippines.js'),
- cambodia: () => import('echarts-countries-js/echarts-countries-js/Cambodia.js'),
- laos: () => import('echarts-countries-js/echarts-countries-js/Laos.js'),
- myanmar: () => import('echarts-countries-js/echarts-countries-js/Myanmar.js'),
- brunei: () => import('echarts-countries-js/echarts-countries-js/Brunei.js'),
- };
- async function initChart() {
- if (!chartRef.value) return;
- if (chartInstance) {
- chartInstance.dispose();
- }
- chartInstance = echarts.init(chartRef.value);
- const countryKey = selectedCountry.value;
- const importFn = countryImportMap[countryKey];
- console.log(importFn);
-
- if (!importFn) {
- chartInstance.setOption({
- title: { text: '地图数据未找到', left: 'center', top: 'center' },
- });
- return;
- }
- let geoJson;
- try {
- const mod = await importFn();
- geoJson = mod.default || mod;
- } catch (e) {
- chartInstance.setOption({
- title: { text: '地图数据加载失败', left: 'center', top: 'center' },
- });
- return;
- }
- echarts.registerMap(countryKey, geoJson);
- const option = {
- tooltip: {
- trigger: 'item',
- formatter: '{b}',
- },
- geo: {
- map: countryKey,
- roam: true,
- emphasis: {
- itemStyle: {
- areaColor: '#a3d5ff',
- },
- },
- },
- series: [
- {
- type: 'map',
- map: countryKey,
- roam: true,
- label: {
- show: true,
- },
- itemStyle: {
- areaColor: '#e0f7fa',
- borderColor: '#333',
- borderWidth: 1
- },
- emphasis: {
- label: { show: true },
- itemStyle: { areaColor: '#a3d5ff' }
- },
- data: [],
- },
- ],
- };
- chartInstance.setOption(option);
- window.addEventListener('resize', handleResize);
- }
- const handleResize = () => {
- if (chartInstance) {
- chartInstance.resize();
- }
- };
- onMounted(() => {
- initChart();
- });
- onUnmounted(() => {
- if (chartInstance) {
- window.removeEventListener('resize', handleResize);
- chartInstance.dispose();
- chartInstance = null;
- }
- });
- </script>
- <style scoped lang="scss">
- .visitor-trend {
- position: relative;
- width: 100%;
- min-height: 300px;
- }
- </style>
|