没接触echarts-for-react之前一直使用的是echarts封装画图,但是突然接到一个需要显示各省的地图切换,查遍了百度也没发现类似的案例。既然我们有画地图的工具ehcarts和各省的地标位置数据那么应该是可以实现的,理论可行,开始实践。
首先我们获取到各省的地表数据
https://github.com/lj-code/city_data/blob/master/%E7%9C%81%E5%B8%82%E5%8E%BF.json
然后我们需要动态的获取地图信息
fetch(`https://geo.datav.aliyun.com/areas_v3/bound/geojson?code=${code}`);
这里我还添加了antd的级联选择组件,是地图的显示精确到了区县地区。详细的页面代码如下:
import React, { useEffect, useState } from 'react';
import { Select, Spin } from 'antd';
import ReactECharts from 'echarts-for-react';
import * as echarts from 'echarts';
import proCityData from './data/proCityCounties.json';
const { Option } = Select;
// 示例数据
const provinceData = proCityData;
// 来源https://github.com/lj-code/city_data/blob/master/%E7%9C%81%E5%B8%82%E5%8E%BF.json
// 异步函数,获取GeoJSON数据
const fetchGeoJson = async (code: string) => {
// 请求对应code的GeoJSON数据
const response = await fetch(`https://geo.datav.aliyun.com/areas_v3/bound/geojson?code=${code}`);
return response.json();
};
const ProvinceMap: React.FC = () => {
const [selectedProvince, setSelectedProvince] = useState<string>(''); // 选中的省份
const [selectedCity, setSelectedCity] = useState<string>(''); // 选中的城市
const [selectedDistrict, setSelectedDistrict] = useState<string>(''); // 选中的区县
const [loading, setLoading] = useState<boolean>(false); // 加载状态
const [option, setOption] = useState<any>({
series: [],
});
// 当选中的省市区变化时,加载相应的GeoJSON数据
useEffect(() => {
const loadGeoJson = async (code: string) => {
setLoading(true); // 开始加载
const geoJson = await fetchGeoJson(code); // 获取GeoJSON数据
echarts.registerMap(code, geoJson); // 注册地图数据
setOption({
series: [
{
type: 'map',
map: code,
roam: true, // 开启缩放和平移
label: {
show: true, // 显示标签
},
itemStyle: {
normal: {
areaColor: '#fde6cf', // 正常状态下区域的颜色
borderColor: 'none' // 边界颜色
},
emphasis: {
areaColor: '#fbb569', // 鼠标移到区域上时的颜色
},
},
},
],
});
setLoading(false); // 加载完成
};
// 优先加载区县地图,其次是城市地图,再次是省份地图
if (selectedDistrict) {
loadGeoJson(selectedDistrict);
} else if (selectedCity) {
loadGeoJson(selectedCity);
} else if (selectedProvince) {
loadGeoJson(selectedProvince);
}
}, [selectedProvince, selectedCity, selectedDistrict]);
// 处理省份选择变化
const handleProvinceChange = (value: string) => {
setSelectedProvince(value); // 设置选中的省份
setSelectedCity(''); // 清空选中的城市
setSelectedDistrict(''); // 清空选中的区县
};
// 处理城市选择变化
const handleCityChange = (value: string) => {
setSelectedCity(value); // 设置选中的城市
setSelectedDistrict(''); // 清空选中的区县
};
// 处理区县选择变化
const handleDistrictChange = (value: string) => {
setSelectedDistrict(value); // 设置选中的区县
};
// 获取指定省份的城市列表
const getCities = (provinceCode: string) => {
const province = provinceData.find(p => p.code === provinceCode);
return province ? province.cityList : [];
};
// 获取指定城市的区县列表
const getDistricts = (cityCode: string) => {
const province = provinceData.find(p => p.cityList.some(c => c.code === cityCode));
const city = province?.cityList.find(c => c.code === cityCode);
return city ? city.areaList : [];
};
return (
<div>
{/* 省份选择器 */}
<div style={{ width: '600' }}>
<Select
style={{ width: 200, marginBottom: 20 }}
placeholder="选择省份"
onChange={handleProvinceChange}
value={selectedProvince}
>
{provinceData.map(province => (
<Option key={province.code} value={province.code}>
{province.name}
</Option>
))}
</Select>
{/* 城市选择器 */}
{selectedProvince && (
<Select
style={{ width: 200, marginBottom: 20, marginLeft: 10 }}
placeholder="选择城市"
onChange={handleCityChange}
value={selectedCity}
>
{getCities(selectedProvince).map(city => (
<Option key={city.code} value={city.code}>
{city.name}
</Option>
))}
</Select>
)}
{/* 区县选择器 */}
{selectedCity && (
<Select
style={{ width: 200, marginBottom: 20, marginLeft: 10 }}
placeholder="选择区县"
onChange={handleDistrictChange}
value={selectedDistrict}
>
{getDistricts(selectedCity).map(district => (
<Option key={district.code} value={district.code}>
{district.name}
</Option>
))}
</Select>
)}
{/* 显示加载状态或地图 */}
<div style={{ width: '600px',height:'600px' }}>
{loading ? <Spin /> : <ReactECharts option={option} style={{ height: 500, width: '100%' }} />}
</div>
</div>
</div>
);
};
export default ProvinceMap;
其中代码注释已经很详细了,希望能帮助到你!
(请注意!页面用到的插件为echarts-for-react,并非只有echarts。)