Introduction to ๐
I believe that every developer of large screen has more or less come into contact with such a requirement: visual data display based on provincial, municipal and district three-level drilling maps. The data display on the map is basically no difficulty for everyone, but the development of the three-stage drilling map really takes some thought.
In order to avoid repeating the wheel, I also developed and optimized several versions of the code of the drill-down map, but ultimately felt unsatisfactory. It was not until recently that the Proxy monitoring mechanism was used for reconstruction to fill in part of the previous experience defects that a relatively satisfactory answer was completed.
Here is to share with you the next development ideas, welcome to exchange ~
๐ source address: three-level drilling map source code
๐ Demo address: three-stage tripping map Demo
If you are helpful, please send a starโญ~
๐ Basic Ideas
If you are familiar with echarts Geo map development, you should know that every time echarts switches a map, it actually registers a static Geo file as the base map, and each map also corresponds to a unique code: Adcode.
We can use Adcode as the core listener for locale switching:
(1) Global register Watcher object to listen for adcode changes;
(2) Trigger the Set hook in the Watcher object during map switching (drill down, return);
(3) Judge and update Adcode in set hook, and obtain geo resources synchronously;
(4) Register new Geo in Echarts to complete map switching.
๐ Core code
I prefer to write code ideas directly in comments, so I won’t go into that here.
/* * @author: AnZhou * @filename: main.js * @description: entry file */
import cityMapByName from '.. /assets/json/cityMapByNameSimple.json';
import cityMapByCode from '.. /assets/json/cityMapByCodeSimple.json';
import STATIC_DATA from '.. /data/staticData';
import mapOption from '.. /data/mapOption';
import getJson from '.. /request/getJson';
import judgeArea from '.. /utils/judgeArea';
let mapIns = null; / / echarts instance
let mapDom = document.getElementById('chart-map'); // Map container
let backBtnDom = document.getElementById('back-btn'); // Returns the parent button
let prevAdcode = null; / / parent adcode
let areaInfo = {}; // For details about the current region, see.. /utils/judgeArea
/** tips--end */ ** tips--end */
let provName = null; // Full name of the province where the current region resides. If no, null
let cityName = null; // Full name of the province where the current region resides. If no, null
let districtName = null; // Full name of the province where the current region resides. If no, null
// Core listener
let watcher = new Proxy({adcode: null.// Adcode for the current field
},
{
get(target, key) {
return target[key];
},
set(target, key, value) {
target[key] = value;
// Get specific information about the current region
areaInfo = judgeArea(watcher.adcode);
// Get the full name of provincial level 3 (if necessary)
getNames();
mapController();
backBtnController();
return true; }});// Control map generation
function mapController() {
/** * tips--start * 1. Click drill down only when local map level is national, provincial or municipal * 2. Municipalities, Macau, Hong Kong, Taiwan are special, only two levels /** TIPS --end */ are displayed
if ([0.1].includes(areaInfo.districtRank)) {
// At the national and provincial levels
prevAdcode = STATIC_DATA.CHINA_ADCODE;
pipeLine();
} else if ([2.3].includes(areaInfo.districtRank)) {
// The current region is city or district
if (areaInfo.isSpecialArea) {
// The parent of the special region is China
prevAdcode = STATIC_DATA.CHINA_ADCODE;
} else {
// The other parents are in their province or autonomous region
prevAdcode = areaInfo.provAdcode;
}
// Just click on the city level to drill down
areaInfo.districtRank == 2&& pipeLine(); }}// Control the return button style
function backBtnController() {
backBtnDom.style.display = areaInfo.districtRank == 0 ? 'none' : 'inline-flex';
}
// Use JSON in cityMapByCode to query the name of a province, city, or district
function getNames() {
/** * tips--start * If your project does not need the full name of the province/county, please delete the following code * and remove the cityMapByCode static JSON */ at the top of the reference
/** tips--end */
[provName, cityName, districtName] = [
areaInfo.provAdcode ? cityMapByCode[areaInfo.provAdcode] : ' ',
areaInfo.cityAdcode ? cityMapByCode[areaInfo.cityAdcode] : ' ',
areaInfo.districtAdcode ? cityMapByCode[areaInfo.districtAdcode] : ' ',]; }// Register to generate echarts maps and bind click events
function initMapChart({ mapDom, mapJson, mapOption }) {
if(! mapIns) { mapIns = echarts.init(mapDom); mapIns.off('click');
mapIns.on('click'.async params => {
watcher.adcode = cityMapByName[params.name];
});
}
echarts.registerMap('Statistical map', mapJson);
mapIns.setOption(mapOption);
}
/ / bus
async function pipeLine() {
// Get geoJSON asynchronously
const mapJson = await getJson(watcher.adcode);
initMapChart({ mapDom, mapJson, mapOption });
}
// Set the container style
mapDom.style.width = '100%';
mapDom.style.height = window.innerHeight - 56 * 2 + 'px';
// Bind returns an event
backBtnDom.addEventListener('click'.() = > {
watcher.adcode = prevAdcode;
});
// Initialize the map
watcher.adcode = '100000';
Copy the code
/* * @author: AnZhou * @filename: judgearea.js * @description: locale information calculation function */
import STATIC_DATA from '.. /data/staticData';
let [provAdcode, cityAdcode, districtAdcode, districtRank, isSpecialArea] = [
...Array(4).fill(null),
false,];function judgeArea(adcode) {
/* * According to the national standard "Administrative Division Code of the People's Republic of China" * Standard no. GB/T 2260-2007 * ADCode code consists of six digits * the first two digits table province, autonomous region level * the second two digits table city, state level * the last two digits table district, county level */
adcode = adcode + ' ';
let result = null;
if (adcode === '100000') {
// Show the map of China
result = [...Array(3).fill(null), 0.false];
} else if (/^\d{2}0{4}$/.test(adcode)) {
// Display maps of provinces and autonomous regions
if (STATIC_DATA.SPECIAL_AREA.includes(adcode)) {
// Provincial level - special area
result = [adcode, adcode, null.1.true];
} else {
/ / province
result = [adcode, null.null.1.false]; }}else if (/^\d{4}0{2}$/.test(adcode)) {
// Display map is city/state level
result = [adcode.substring(0.2) + '0000', adcode, null.2, isSpecialArea];
} else {
// Display the map (select region as)
result = [
adcode.substring(0.2) + '0000',
adcode.substring(0.4) + '00',
adcode,
3,
isSpecialArea,
];
}
[provAdcode, cityAdcode, districtAdcode, districtRank, isSpecialArea] = result;
return {
provAdcode, / / adcode at the provincial level
cityAdcode, / / municipal adcode
districtAdcode, / / district-level adcode
districtRank, // Current map level: 0- Country 1- Province 2- City 3- District
isSpecialArea, // Whether special area
};
}
export default judgeArea;
Copy the code
๐ Other code
Due to limited space non-core code will not be posted, interested can go to Github to check.
๐ Additional note
๐ฉ 1. Where does the Geojson file come from?
(1) Ali DataV’s GeoJSON open platform. In this demo, all the static files are stored in git repository (click to see) and then returned by jsdelivrCDN.
(2) Clever use of Autonavi open platform’s administrative area query API (THIS method I have not tried, we understand the next).
๐ฉ 2. Why is there no transition effect when I switch maps?
Echarts4.3 and above does not have the transition effect of map switching. If you want to use the transition effect, you must use Echarts4.3 and below (not too old, of course).
As an aside, transition effects are expected to return in 5.3, see issue for details.
๐ฉ 3. Is there a Vue/React version?
Not at the moment, but I’m sure migration won’t be a problem for everyone.
๐ฉ 4. Why cannot I see the effect on the page after I modify the source code?
This Demo uses Rollup, which must be repackaged every time the source code is changed. As for why hot update is not possible, because rollup’s hot update plugin installation is always wrong, it did not add this feature. There will be no Rollup in formal projects, ๐.
๐ฉ 4. This code doesn’t work, I have a better one!
Welcome to ๐ฅณ๐ฅณ~