vue-echarts map地图动态下钻,自定义标注,tooltip弹窗
- 效果展示:
- 资源准备:
1. 地图json下载链接:
免费下载实时更新的geoJson数据、行政区划边界数据、区划边界坐标集合__HashTang
2. 地图接送下载链接2(阿里云):
DataV.GeoAtlas地理小工具系列
2.2 新建down.js文件,打开cmd命令框,输入node down.js即可下载地图资源(阿里云中下载的中国地图资源加载不出来),以下是down.js核心代码:
const fs = require('fs'); const path = require('path'); const https = require('https'); const readline = require('readline'); // 基础配置 // 这是地图的下载地址 const baseUrl = 'https://geo.datav.aliyun.com/areas_v3/bound/'; // 这是所有地区编码 const infoUrl = 'https://geo.datav.aliyun.com/areas_v3/bound/infos.json'; // 控制直辖市下级区是否放在 citys 文件夹下(便于地图下钻的逻辑处理) const MUNICIPALITIES = ['110000', '120000', '310000', '500000']; // 北京、天津、上海、重庆 let municipalityChildrenInCitys; // 控制直辖市下级区是否放在 citys 文件夹下 // 当前正在写入的文件路径(用于 SIGINT 清理) let currentWritingFile = null; // Ctrl+C 时清理不完整的文件 process.on('SIGINT', () => { console.log(`\n${colors.yellow}⚠${colors.reset} 检测到中断信号 (Ctrl+C)...`); if (currentWritingFile && fs.existsSync(currentWritingFile)) { try { fs.unlinkSync(currentWritingFile); console.log(`${colors.yellow}⚠${colors.reset} 已清理不完整文件: ${colors.cyan}${currentWritingFile}${colors.reset}`); } catch (err) { console.error(`${colors.red}✗${colors.reset} 清理文件失败:`, err.message); } } console.log(`${colors.blue}ℹ${colors.reset} 程序已退出\n`); process.exit(0); }); // // 这是输出目录 // const outputDir = './'; // // 添加命名方式配置 // const config = { // nameFormat: 'adcode', // 可选值: 'adcode', 'chinese' // }; // 命令行交互 const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); const question = (query) => new Promise((resolve) => rl.question(query, resolve)); // ANSI 颜色代码 终端进度条用 const colors = { reset: '\x1b[0m', bright: '\x1b[1m', dim: '\x1b[2m', red: '\x1b[31m', green: '\x1b[32m', yellow: '\x1b[33m', blue: '\x1b[34m', magenta: '\x1b[35m', cyan: '\x1b[36m', white: '\x1b[37m', bgBlue: '\x1b[44m', }; // 进度条类 class ProgressBar { constructor(name, total, width = 30) { this.name = name; this.total = total; this.current = 0; this.width = width; } update(current, currentItem = '') { this.current = current; const percentage = Math.round((this.current / this.total) * 100); const filledWidth = Math.round(this.width * (this.current / this.total)); const emptyWidth = this.width - filledWidth; const filled = '█'.repeat(filledWidth); const empty = '░'.repeat(emptyWidth); const bar = `${filled}${empty}`; if (process.stdout.isTTY) { process.stdout.clearLine(0); process.stdout.cursorTo(0); process.stdout.write( `${colors.magenta}♦${colors.reset} ${colors.bright}${this.name}${colors.reset} ` + `${colors.cyan}${bar}${colors.reset} ${colors.yellow}${percentage}%${colors.reset} ` + `(${this.current}/${this.total}) ${colors.dim}${currentItem}${colors.reset}` ); } else { // 非 TTY 环境:简化输出,避免刷屏 if (this.current === this.total || this.current % 10 === 0) { console.log(`[${this.name}] ${percentage}% (${this.current}/${this.total}) ${currentItem}`); } } } complete() { process.stdout.write('\n'); } } // 创建目录 const createDir = (dir) => { if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } }; // 修改 HTTPS 请求函数,添加重试机制 const httpsGet = async (url, retries = 3) => { for (let i = 0; i < retries; i++) { try { const response = await new Promise((resolve, reject) => { https.get(url, (res) => { if (res.statusCode !== 200) { // 消耗响应流释放资源,防止内存泄漏 res.resume(); reject(new Error(`HTTP 状态码: ${res.statusCode}`)); return; } let data = ''; res.on('data', (chunk) => data += chunk); res.on('end', () => resolve(data)); }).on('error', reject); }); try { return JSON.parse(response); } catch (parseError) { // 如果是最后一次重试,则抛出错误 if (i === retries - 1) { throw new Error(`JSON 解析失败: ${parseError.message}`); } // 否则继续重试 await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1))); // 递增延迟 continue; } } catch (error) { // 如果是最后一次重试,则抛出错误 if (i === retries - 1) { throw error; } // 否则继续重试 await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1))); // 递增延迟 continue; } } }; // 修改 getFileName 函数,添加对全国地图的特殊处理 const getFileName = (code, info, type = '', nameFormat) => { // 如果是全国地图(代码为100000),则返回 china.json if (code === '100000') { return 'china.json'; } switch (nameFormat) { case 'chinese': return `${info.name}${type}.json`; case 'adcode': default: return `${code}.json`; } }; // 追踪写入状态,便于中断时清理 const safeWriteFile = (filePath, content) => { currentWritingFile = filePath; fs.writeFileSync(filePath, content); currentWritingFile = null; // 写入完成清除追踪 }; // 修改 downloadJson 函数,添加 useFullVersion 参数 const downloadJson = async (url, outputPath, info, progressBar = null, currentItem = '', useFullVersion = false) => { try { // 如果需要下载 full 版本,先尝试下载 if (useFullVersion) { try { const fullUrl = url.replace('.json', '_full.json'); const data = await httpsGet(fullUrl); safeWriteFile(outputPath, JSON.stringify(data)); if (progressBar) { progressBar.update(progressBar.current + 1, currentItem); } else { console.log(`${colors.green}✓${colors.reset} 成功下载: ${colors.cyan}${outputPath}${colors.reset}`); } return; } catch (error) { console.log(`${colors.yellow}!${colors.reset} full 版本下载失败,尝试基础版本...`); } } // 下载基础版本 const data = await httpsGet(url); safeWriteFile(outputPath, JSON.stringify(data)); if (progressBar) { progressBar.update(progressBar.current + 1, currentItem); } else { console.log(`${colors.green}✓${colors.reset} 成功下载: ${colors.cyan}${outputPath}${colors.reset}`); } await new Promise(resolve => setTimeout(resolve, 200)); } catch (error) { console.error(`${colors.red}✗${colors.reset} 下载失败: ${colors.cyan}${url}${colors.reset}`, error.message); if (progressBar) { progressBar.update(progressBar.current + 1, `${colors.red}${currentItem} (失败)${colors.reset}`); } } }; // 主函数 const main = async () => { try { console.log('\n' + colors.bright + colors.bgBlue + ' 中国地图数据下载工具 ' + colors.reset + '\n'); // 获取用户输入的输出目录 const outputDir = await question(`${colors.yellow}请输入输出目录路径 (直接回车默认为当前目录):${colors.reset}`); const finalOutputDir = outputDir || './'; // 获取地区信息用于省份选择 console.log(`${colors.blue}ℹ${colors.reset} 正在获取地区信息...`); const areaInfos = await httpsGet(infoUrl); if (!areaInfos) { console.error(`${colors.red}✗${colors.reset} 获取地区信息失败`); return; } console.log(`${colors.green}✓${colors.reset} 地区信息获取成功\n`); // 提取所有省级行政区 const provinces = Object.entries(areaInfos) .filter(([code]) => code.endsWith('0000') && code !== '100000') .map(([code, info]) => ({ code, name: info.name })); // 选择下载范围:全部省份 or 指定省份 const downloadScopeAnswer = await question(`${colors.yellow}请选择下载范围 (1: 全部省份, 2: 选择指定省份) [默认: 1]:${colors.reset}`); let selectedProvinces = provinces; // 默认全部省份 if (downloadScopeAnswer === '2') { // 列出所有省份 console.log(`\n${colors.bright}可选省份列表:${colors.reset}`); provinces.forEach((province, index) => { const num = String(index + 1).padStart(2, ' '); // 每行显示4个省份 const suffix = (index + 1) % 4 === 0 ? '\n' : '\t'; process.stdout.write(`${colors.cyan}${num}.${colors.reset} ${province.name}${suffix}`); }); // 确保换行 if (provinces.length % 4 !== 0) console.log(''); console.log(''); const provinceIndexAnswer = await question(`${colors.yellow}请输入省份序号,多个用英文逗号分隔 (如: 1,5,11):${colors.reset}`); // 解析输入的多个序号 const inputIndices = provinceIndexAnswer.split(',').map(s => s.trim()); const validProvinces = []; const invalidIndices = []; for (const indexStr of inputIndices) { const idx = parseInt(indexStr, 10) - 1; if (idx >= 0 && idx < provinces.length && !isNaN(idx)) { // 避免重复添加 if (!validProvinces.find(p => p.code === provinces[idx].code)) { validProvinces.push(provinces[idx]); } } else { invalidIndices.push(indexStr); } } // 报告无效序号 if (invalidIndices.length > 0) { console.log(`${colors.yellow}⚠${colors.reset} 忽略无效序号: ${invalidIndices.join(', ')}`); } if (validProvinces.length === 0) { console.error(`${colors.red}✗${colors.reset} 没有有效的省份序号,退出程序`); return; } selectedProvinces = validProvinces; const selectedNames = selectedProvinces.map(p => p.name).join('、'); console.log(`${colors.green}✓${colors.reset} 已选择 ${colors.bright}${selectedProvinces.length}${colors.reset} 个省份: ${colors.bright}${selectedNames}${colors.reset}\n`); } // 获取用户选择的命名方式 const nameFormatAnswer = await question(`${colors.yellow}请选择文件命名方式 (1: 行政代码, 2: 中文名称) [默认: 1]:${colors.reset}`); const nameFormat = nameFormatAnswer === '2' ? 'chinese' : 'adcode'; // 获取省级地图数据粒度 const provinceLevelAnswer = await question(`${colors.yellow}请选择省级地图数据粒度 (1: 包含市级边界, 2: 包含区县级边界, 3: 不包含下级边界) [默认: 1]:${colors.reset}`); const provinceLevel = provinceLevelAnswer === '2' ? 2 : (provinceLevelAnswer === '3' ? 3 : 1); // 获取市级地图数据粒度 const cityLevelAnswer = await question(`${colors.yellow}请选择市级地图数据粒度 (1: 包含区县级边界, 2: 不包含下级边界) [默认: 1]:${colors.reset}`); const cityLevel = cityLevelAnswer === '2' ? 2 : 1; // 添加直辖市下级区存放位置的选择 const municipalityAnswer = await question(`${colors.yellow}是否将直辖市下级区地图放在citys文件夹下(便于地图下钻的逻辑处理)(y/n) [默认: y]:${colors.reset}`); municipalityChildrenInCitys = municipalityAnswer.toLowerCase() !== 'n'; // 创建输出目录 createDir(finalOutputDir); createDir(path.join(finalOutputDir, 'province')); createDir(path.join(finalOutputDir, 'citys')); createDir(path.join(finalOutputDir, 'county')); // 保存压缩版的 info.json fs.writeFileSync(path.join(finalOutputDir, 'info.json'), JSON.stringify(areaInfos)); console.log(`${colors.green}✓${colors.reset} 地区信息已保存至 info.json`); // 计算总任务数(基于选中的省份) let totalFiles = 1; // 全国地图 for (const province of selectedProvinces) { const provinceCode = province.code; const cities = Object.entries(areaInfos).filter(([code]) => code.startsWith(provinceCode.slice(0, 2)) && code.endsWith('00') && code !== provinceCode ); totalFiles++; // 省级地图 totalFiles += cities.length; // 市级地图 for (const [cityCode] of cities) { const counties = Object.entries(areaInfos).filter(([code]) => code.startsWith(cityCode.slice(0, 4)) && !code.endsWith('00') ); totalFiles += counties.length; // 县级地图 } } console.log(`${colors.blue}ℹ${colors.reset} 总计需要下载 ${colors.yellow}${totalFiles}${colors.reset} 个地图文件`); console.log(`${colors.blue}ℹ${colors.reset} 共有 ${colors.yellow}${selectedProvinces.length}${colors.reset} 个省级行政区待下载\n`); // 下载全国地图 const chinaInfo = areaInfos['100000']; await downloadJson( `${baseUrl}100000.json`, path.join(finalOutputDir, getFileName('100000', chinaInfo, '', nameFormat)), chinaInfo ); console.log(`${colors.blue}→${colors.reset} 全国地图下载完成\n`); // 处理选中的省级数据 for (const province of selectedProvinces) { const provinceCode = province.code; const info = areaInfos[provinceCode]; // 获取所有下级行政区 const cities = Object.entries(areaInfos).filter(([code]) => code.startsWith(provinceCode.slice(0, 2)) && code.endsWith('00') && code !== provinceCode ); const counties = Object.entries(areaInfos).filter(([code]) => code.startsWith(provinceCode.slice(0, 2)) && !code.endsWith('00') ); // 计算该省的总任务数 let provinceTotalTasks = 1; // 省级地图 // 添加市级地图任务数 if (provinceLevel !== 3) { provinceTotalTasks += cities.length; } // 添加区县级地图任务数(如果需要) if (provinceLevel === 2 || (provinceLevel !== 3 && cityLevel === 1)) { provinceTotalTasks += counties.length; } console.log(`${colors.blue}→${colors.reset} 开始处理: ${colors.bright}${info.name}${colors.reset}`); console.log(`${colors.blue}ℹ${colors.reset} 需要下载 ${colors.yellow}${provinceTotalTasks}${colors.reset} 个地图文件`); const progressBar = new ProgressBar(info.name, provinceTotalTasks); // 下载省级地图(根据选择的粒度决定是否使用 full 版本) await downloadJson( `${baseUrl}${provinceCode}.json`, path.join(finalOutputDir, 'province', getFileName(provinceCode, info, '', nameFormat)), info, progressBar, '省级地图', provinceLevel !== 3 // 如果不是跳过下级边界,则尝试下载 full 版本 ); // 如果不是跳过下级边界 if (provinceLevel !== 3) { // 下载市级地图 for (const [cityCode, cityInfo] of cities) { await downloadJson( `${baseUrl}${cityCode}.json`, path.join(finalOutputDir, 'citys', getFileName(cityCode, cityInfo, '', nameFormat)), cityInfo, progressBar, `市级: ${cityInfo.name}`, cityLevel === 1 // 如果选择包含区县级边界,则尝试下载 full 版本 ); } // 下载区县级地图(如果需要) if (provinceLevel === 2 || cityLevel === 1) { for (const [countyCode, countyInfo] of counties) { // 确定目标目录 const isMunicipality = MUNICIPALITIES.includes(provinceCode); const targetDir = (isMunicipality && municipalityChildrenInCitys) ? 'citys' : 'county'; await downloadJson( `${baseUrl}${countyCode}.json`, path.join(finalOutputDir, targetDir, getFileName(countyCode, countyInfo, '', nameFormat)), countyInfo, progressBar, `区县: ${countyInfo.name}` ); } } } progressBar.complete(); console.log(`${colors.green}✓${colors.reset} ${colors.bright}${info.name}${colors.reset} 处理完成!\n`); } console.log(`${colors.green}✨${colors.reset} ${colors.bright}所有地图数据下载完成!${colors.reset}\n`); } catch (error) { console.error(`${colors.red}错误:${colors.reset}`, error.message); } finally { rl.close(); } }; // 添加错误处理 process.on('unhandledRejection', (error) => { console.error(`${colors.red}✗${colors.reset} 未处理的 Promise 拒绝:`, error); process.exit(1); }); main();- 代码片段:
<template> <div class="map-box"> <v-chart :option="mapOption" class="map-chart" @click="handleMapClick" :resizeable="true"/> <!-- 通过v-chart组件渲染地图 --> <el-button type="warning" class="back-btn" @click="handleBack">返回上一级</el-button> </div> </template> <script setup> import { ref, provide, onMounted, watch } from 'vue' import VChart, { THEME_KEY } from 'vue-echarts' // 引入v-chart组件 import * as echarts from 'echarts' // 引入echarts import ChinaGroJson from '@/assets/map-json/100000.json' // 引入全国地图json文件,这里只引入全国地图json文件即可 import ziben2 from '@/assets/images/digitalTwin/ziben2.png' // 引入全国地图json文件,这里只引入全国地图json文件即可 import axios from 'axios' import { useRouter } from 'vue-router' const router = useRouter() provide(THEME_KEY, 'light') // 提供主题:dark / light const props = defineProps({ dialogContent: { type: Object, default: {} } }) watch(() => props.dialogContent, (newVal) => { }, {deep: true }); const mapOption = ref() // 地图配置 const geoJson = { // 地图json数据 只初始化全国地图json文件,其他省市县地图json文件在下面代码里动态获取,例如:当前地图切换为北京,则geoJson.province存储的就是北京市的地图json数据,切换为天津,则geoJson.province存储的就是天津市的地图json数据 china: ChinaGroJson, province: null, // 省 city: null, // 市 county: null // 县 } const currentLevel = ref('china') // 当前地图级别,默认为全国 const levelConfig = { // 地图层级配置,用于描述地图的层级关系 china: { nextLevel: 'province', // 下一级,表示点击地图后,地图要跳转到的下一级 geoKey: 'china', // 地图key,表示地图的层级名称 jsonPath: 'province' // 地图json路径,表示地图json文件的存储路径 }, province: { nextLevel: 'city', geoKey: 'province', jsonPath: 'citys' }, city: { nextLevel: 'county', geoKey: 'city', jsonPath: 'county' } } // 文本 const geoText = ref({ china: 'china', province: null, // 省 city: null, // 市 county: null // 县 }) const showDialog = ref(true) /** * 设置地图option,这里直接使用最基础的地图配置,可以根据需求自行修改 * @param {Array} mapData 地图要用的data数据 * @param {String} mapName 地图名称 */ const setMapOption = (mapData, mapName = 'china') => { mapOption.value = { tooltip: { trigger: 'item', triggerOn: "mousemove|click", // 触发条件 backgroundColor: "rgba(22, 12, 5, 0.96)", borderColor: '#f2a13b', borderWidth: 1, padding: [8, 12], textStyle: { color: "#fff5e7", fontSize: 13 }, axisPointer: { type: "line", lineStyle: { color: "rgba(255, 203, 112, 0.75)", width: 1 }, }, formatter: '{b}' // 鼠标悬浮显示地区名称 // 数据格式化 // formatter: function(params) { // return ( // params.seriesName + "<br />" + params.name + ":" + params.value // ); // }, }, // backgroundColor: "#0E2152", // 背景颜色 series: [ // { // name: mapName == "全国" ? "china" : mapName, // type: 'map', // map: mapName, // roam: false, // 开启缩放和平移 // data: mapData // }, { type: currentLevel.value == 'county' ? "scatter" : "effectScatter", // effectScatter|scatter:带有涟漪特效动画的散点(气泡)图 coordinateSystem: "geo", //该系列使用的坐标系:地理坐标系 effectType: "ripple", // 特效类型,目前只支持涟漪特效'ripple',意为“涟漪” showEffectOn: "render", // 配置何时显示特效。可选'render'和'emphasis' rippleEffect: { // 涟漪特效相关配置。 period: 10, // 动画的周期,秒数。 scale: 4, // 动画中波纹的最大缩放比例。 brushType: "fill", // 波纹的绘制方式,可选 'stroke' 和 'fill'。 }, zlevel: 1, // 这里是关键,一定要放在 series中,显示层级, hoverAnimation: true, itemStyle: { normal: { // color: function(params){ // return levelColorMap[params.value[3]]; // }, color: 'rgba(255, 235, 59, .7)', shadowBlur: 10, shadowColor: '#333' } }, tooltip: { trigger: "item", backgroundColor: "transparent", borderColor: "transparent", formatter: function (params) { return formatHtml(params.data); }, }, // symbol: `image://${require("@/assets/img/point.png")}`, symbol: currentLevel.value == 'county' ? `image://${new URL("@/assets/images/digitalTwin/默认.png", import.meta.url)}` : '', symbolSize: currentLevel.value == 'county' ? [64, 36] : [8, 8], // symbolOffset: [-5, 0], label: { formatter: '{b}', position: 'insideTop', show: currentLevel.value == 'county' ? true : false, textStyle: { color: '#fff', fontSize: 12, } }, // data: gatewayPointData.value[mapName] ? gatewayPointData.value[mapName] : gatewayPointData.value[geoText.value[currentLevel.value]], // 筛选显示 data: [ { name: "鹿洼煤矿", value: [116.59,35.10], companyId: 583871900 }, { name: "化学公司", value: [116.55,35.10], companyId: 1101552392322834400 }, { name: "热电公司", value: [116.54,35.085], companyId: 1101552392322834400 }, { name: "建材公司", value: [116.58,35.08], companyId: 1101552768161833000 }, { name: "鲁泰集团", value: [116.60,35.37], companyId: 1002198288 }, { name: "太平煤矿", value: [116.77,35.37], companyId: 1101552392322834400 }, { name: "鲁泰矿业西北分公司", value: [109.76,38.28] }, { name: "新疆明基能源", value: [86.48,43.82] }, ], }, ], geo: { map: mapName == "全国" ? "china" : mapName, // roam: false, label: { // 图形上的文本标签 normal: { // 通常状态下的样式 show: true, textStyle: { color: "#fff", }, }, emphasis: { // 鼠标放上去高亮的样式 textStyle: { color: "#fff", }, }, }, itemStyle: { normal: { // 地图区域的样式设置 borderColor: "#f2a13b", borderWidth: 1, areaColor: { // image: 'image://${require("@/assets/img/china-map.png")}', // repeat: "repeat", type: "radial", // 径向渐变 x: 0.5, // 圆心 y: 0.5, // 圆心 r: 0.8, // 半径 colorStops: [ { offset: 0, color: "rgba(242, 161, 59, 0)", }, // 0% 处的颜色 { offset: 0.5, color: "rgba(242, 161, 59, .6)", },// 100% 处的颜色 { offset: 1, color: "rgba(242, 161, 59, .4)", },// 100% 处的颜色 ], // colorStops: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ // ]), }, shadowColor: "rgba(78, 59, 45, 0.8)", //底层颜色 shadowOffsetX: 9, shadowOffsetY: 8, }, emphasis: { // 鼠标放上去高亮的样式 areaColor: "#99631d", borderWidth: 0, }, }, }, } } const gatewayPointData = ref({ 'china': [ { name: "山东省", value: [118.03,36.67] }, { name: "陕西省", value: [108.96,34.28] }, { name: "新疆维吾尔自治区", value: [87.63,43.80] }, ], '山东省': [ { name: "济宁市", value: [116.59,35.42] }, ], '陕西省': [ { name: "榆林市", value: [109.74,38.29] }, ], '新疆维吾尔自治区': [ { name: "昌吉回族自治州", value: [90.01,44.02] }, ], '济宁市': [ { name: "鱼台县", value: [116.66,35.02] }, { name: "任城区", value: [116.55,35.49] }, { name: "邹城市", value: [117.01,35.41] }, ], '榆林市': [ { name: "榆阳区", value: [109.73,38.28] }, ], '昌吉回族自治州': [ { name: "呼图壁县", value: [86.51,43.82] }, ], '鱼台县': [ { name: "鹿洼煤矿", value: [116.59,35.10], companyId: 583871900 }, { name: "化学公司", value: [116.55,35.10], companyId: 1101552392322834400 }, { name: "热电公司", value: [116.54,35.085], companyId: 1101552392322834400 }, { name: "建材公司", value: [116.58,35.08], companyId: 1101552768161833000 }, ], '任城区': [ { name: "鲁泰集团", value: [116.60,35.37], companyId: 1002198288 }, ], '邹城市': [ { name: "太平煤矿", value: [116.77,35.37], companyId: 1101552392322834400 }, ], '榆阳区': [ { name: "鲁泰矿业西北分公司", value: [109.76,38.28] }, ], '呼图壁县': [ { name: "新疆明基能源", value: [86.48,43.82] }, ] }) let landmarkArr = ref([]) const formatHtml = ({name, companyId}) => { const targetCompany = props.dialogContent.find( (v) => v.companyId === companyId ) if(!targetCompany) return return ` <div class="dialog"> <div class="title">${name}</div> <div class="dialog-middle"> <div class="dialog-middle-box"> <div class="left"> <img src="${ziben2}" alt="" /> <div> <p>注册资本/万元</p> <p>¥${targetCompany.funds}</p> </div> </div> <div class="right"> <img src="${ziben2}" alt="" /> <div> <p>${targetCompany.honor ? targetCompany.honor : ''}</p> <p>${targetCompany.remark ? targetCompany.remark : ''}</p> </div> </div> </div> </div> <div class="dialog-content">${ targetCompany.introduce }</div> </div> `; } const handleMapClick = async event => { // 地图点击事件 // console.log(event) const currentConfig = levelConfig[currentLevel.value] // 获取当前地图层级配置 if(event.name === '南海诸岛') return if (currentConfig) { currentLevel.value = currentConfig.nextLevel // 更新当前层级,把下一级作为当前层级存储到currentLevel中 const adcode = geoJson[currentConfig.geoKey].features.find(item => item.properties.name === event.name).properties.adcode // 获取地区编码,从geoJson中对应层级存储的json文件中获取 try { // const newGeoJson = await import(`@/assets/map-json/${currentConfig.jsonPath}/${adcode}.json`) // 动态获取下一级地图json文件, 例如:@/assets/map-json/citys/110100.json const newGeoJson = await (await axios.get(`map-json/${currentConfig.jsonPath}/${adcode}.json`)).data geoJson[currentConfig.nextLevel] = newGeoJson // 将获取到的地图json数据赋值到geoJson里对应的层级 geoText.value[currentLevel.value] = event.name echarts.registerMap(event.name, geoJson[currentConfig.nextLevel]) // 注册新地图 if(currentConfig.nextLevel === 'county') { if(gatewayPointData.value[event.name]) landmarkArr.value = gatewayPointData.value[event.name] } setMapOption(['地图数据'], event.name) // 设置新地图配置 } catch (error) { console.log('地图数据加载失败', error) handleBack() // 如果加载失败,则返回上一级 } } else { const filterData = landmarkArr.value.filter(obj => obj.name === event.name) if(filterData?.[0].companyId) { // TODO: 我需要跳转vue页面哦 router.push({ path: '/digitalTwin/Dt', query: { name: event.name } }) } } } // 返回上一级 const handleBack = () => { if (currentLevel.value === 'china') return // 如果已经是最顶层则不处理 const prevLevels = { province: 'china', city: 'province', county: 'city' } const prevLevel = prevLevels[currentLevel.value] // 获取上一级配置 currentLevel.value = prevLevel // 返回上一级 echarts.registerMap(prevLevel, geoJson[prevLevel]) // 重新注册上一级地图,例如我们当前层级是青岛市地图,geoJson.province依然存储着山东省的地图,此时我们直接使用即可 setMapOption(['地图数据'], prevLevel) // 设置新地图配置 } // 组件挂载初始化全国地图 onMounted(() => { echarts.registerMap('china', geoJson.china) setMapOption(['地图数据'], 'china') }) </script> <style lang="scss" scoped> .map-box { box-sizing: border-box; position: relative; width: 100%; height: 100%; // background: url("@/assets/images/digitalTwin/dashboard-bg.png") no-repeat; .back-btn { position: absolute; // color: #755628; color: #ffffff; background-color: rgba(29, 27, 23, 0.6); top: 3vw; left: 0; } } .map-chart { width: 100%; height: 100%; } :deep(.dialog) { width: vw(357); height: vw(200); background: url('@/assets/images/digitalTwin/弹框.png') no-repeat; background-size: 100% 100%; margin-left: vw(10); position: absolute; z-index: 99999; padding: vw(12); .title { margin-left: vw(20); font-weight: 600; font-size: vw(16); margin-top: vw(-8); } .dialog-middle { height: vw(70); margin-top: vw(10); } .dialog-middle-box { display: flex; height: 100%; justify-content: space-around; align-items: center; .left, .right { flex: 1; height: vw(62); background: url('@/assets/images/digitalTwin/center_item.png') no-repeat; background-size: 100% 100%; display: flex; div { display: flex; flex-direction: column; justify-content: space-evenly; align-items: flex-end; margin-left: vw(5); :first-child { color: #ffba57; font-size: vw(14); } :nth-child(2) { background-image: linear-gradient( to bottom, #ffffff 70%, #ffd493 30% ); font-size: vw(16); font-weight: 700; -webkit-background-clip: text; font-family: AlimamaShuHeiTi, sans-serif; background-clip: text; color: transparent; } p { display: -webkit-box; -webkit-line-clamp: 1; /* 👈 要显示几行就填几 */ -webkit-box-orient: vertical; overflow: hidden; white-space: wrap; text-overflow: ellipsis; } } img { width: vw(32); height: vw(32); margin-top: vw(14); margin-left: vw(18); } } .left { margin-right: vw(14); } } .dialog-content { line-height: vw(25); font-size: vw(16); display: -webkit-box; -webkit-line-clamp: 4; /* 👈 要显示几行就填几 */ -webkit-box-orient: vertical; overflow: hidden; /*这两行代码可以解决大部分场景下的换行问题*/ word-break: break-all; word-wrap: break-word; /*但在有些场景中,还需要加上下面这行代码*/ white-space: normal; } } </style>- 资源片段
- 其它相关案例参考:
echarts map地图动态下钻,自定义标注,自定义tooltip弹窗【完整demo版本】_地图下钻-CSDN博客
