This article demonstrates how to create an interactive COVID-19 map of China using Apache ECharts. Two approaches are covered: fetching live data from the Tencent API and consuming server-side data (e.g., from a Java backend). The visual map uses piecewise coloring to reflect confirmed case ranges across provinces.
Approach 1: Fetching Live Data from Tencent API
The following HTML page loads ECharts and the China map plugin, then retrieves province-level confirmed case data via JSONP from the Tencent public endpoint.
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>COVID-19 China Map</title>
<style>
#mapContainer { width: 800px; height: 500px; margin: 20px auto; border: 1px solid #ddd; }
</style>
<!-- ECharts CDN -->
<script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>
<!-- China map registration -->
<script src="https://cdn.jsdelivr.net/npm/echarts@5/map/json/china.json"></script>
</head>
<body>
<div id="mapContainer"></div>
<script>
const chart = echarts.init(document.getElementById('mapContainer'));
const option = {
title: { text: 'Confirmed Cases in China', left: 'center' },
tooltip: { trigger: 'item' },
visualMap: {
type: 'piecewise',
pieces: [
{ min: 10000, label: '≥10k', color: '#4e160f' },
{ min: 1000, max: 9999, label: '1k-9,999', color: '#974236' },
{ min: 100, max: 999, label: '100-999', color: '#ee7263' },
{ min: 1, max: 99, label: '1-99', color: '#f5bba7' }
],
color: ['#E0022B', '#E09107', '#A3E00B']
},
toolbox: {
show: true, orient: 'vertical', left: 'right', top: 'center',
feature: { mark: true, dataView: { readOnly: false }, restore: true, saveAsImage: true }
},
series: [{
name: 'Confirmed',
type: 'map',
map: 'china',
roam: false,
label: { show: true, color: '#fff' },
data: []
}]
};
chart.setOption(option);
// Fetch data from Tencent API
fetch('https://view.inews.qq.com/g2/getOnsInfo?name=disease_h5')
.then(response => response.json())
.then(result => {
const raw = result.data || '{}';
const parsed = JSON.parse(raw);
const provinces = parsed.areaTree[0].children;
const data = provinces.map(p => ({ name: p.name, value: p.total.confirm }));
chart.setOption({ series: [{ data: data }] });
})
.catch(console.error);
</script>
</body>
</html>
The API returns a nested structure; we extract province names and confirmed counts. Note that ECharts map built-in names must match exactly (e.g., "北京" not "北京市"). The Tencent API uses short names that align with the China map, so no nameMap is required.
Approach 2: Using Server-Side Data (Java/JSP)
If your data comes from a backend (e.g., a Java servlet), you can embed the data as a JSON array in the page. Below is a simplified JSP snippet that renders the map with server-provided province data.
<%@ page import="java.util.List" %>
<!-- Assume "list" attribute contains ProvinceData objects with name and confirmed -->
<html>
<head>
<meta charset="UTF-8">
<title>Server-Side China Map</title>
<style>
#chart { width: 800px; height: 500px; margin: auto; }
</style>
<script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/echarts@5/map/json/china.json"></script>
</head>
<body>
<div id="chart"></div>
<script>
const chart = echarts.init(document.getElementById('chart'));
const serverData = [
<%
List<ProvinceData> list = (List<ProvinceData>) request.getAttribute("list");
if (list != null) {
for (int i = 0; i < list.size(); i++) {
ProvinceData p = list.get(i);
// Escape names properly
String name = p.getName().replace("'", "\\'");
out.print("{ name: '" + name + "', value: " + p.getConfirmed() + " }");
if (i < list.size() - 1) out.print(", ");
}
}
%>
];
const option = {
title: { text: 'Confirmed Cases (Server Data)', left: 'center' },
tooltip: { trigger: 'item' },
visualMap: {
type: 'piecewise',
pieces: [
{ min: 10000, label: '≥10k', color: '#4e160f' },
{ min: 1000, max: 9999, label: '1k-9,999', color: '#974236' },
{ min: 100, max: 999, label: '100-999', color: '#ee7263' },
{ min: 1, max: 99, label: '1-99', color: '#f5bba7' }
]
},
series: [{
type: 'map',
map: 'china',
data: serverData,
label: { show: true, color: '#fff' }
}]
};
chart.setOption(option);
</script>
</body>
</html>
If the backend uses province full names (e.g., "北京市") that differ from the map's built-in names, you can apply a nameMap to translate. Alternatively, store the data using the map's default short names to avoid mapping.
Key Considerations
- Map Registration: Always load the China JSON map file after ECharts. As of ECharts 5, you can use
echarts.registerMap('china', chinaJson)if you load the JSON directly. - Data Matching: Province names in the data array must match exactly the names used in the map. The built-in China map uses short names like "北京", "天津", "上海", etc.
- API Changes: The Tencent API endpoint may change. Always handle errors and check resposne structure.
- Province Drill-Down: To allow clicking into a province, you can listen to the
clickevent and load a sub-map (city-level data). This is a advanced extension not covered here.