发布时间:2026/8/6 12:05:12
vue-echarts map地图动态下钻,自定义标注,tooltip弹窗 效果展示资源准备1. 地图json下载链接免费下载实时更新的geoJson数据、行政区划边界数据、区划边界坐标集合__HashTang2. 地图接送下载链接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; // CtrlC 时清理不完整的文件 process.on(SIGINT, () { console.log(\n${colors.yellow}⚠${colors.reset} 检测到中断信号 (CtrlC)...); 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 classmap-box v-chart :optionmapOption classmap-chart clickhandleMapClick :resizeabletrue/ !-- 通过v-chart组件渲染地图 -- el-button typewarning classback-btn clickhandleBack返回上一级/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 classdialog div classtitle${name}/div div classdialog-middle div classdialog-middle-box div classleft img src${ziben2} alt / div p注册资本/万元/p p${targetCompany.funds}/p /div /div div classright img src${ziben2} alt / div p${targetCompany.honor ? targetCompany.honor : }/p p${targetCompany.remark ? targetCompany.remark : }/p /div /div /div /div div classdialog-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 langscss 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博客

相关新闻

2026/8/6 12:05:12

AI原生应用中的API编排技术实践与优化

1. 项目概述:AI原生应用与API编排的数字化转型价值最近两年,企业服务领域最显著的变化就是AI技术从"附加功能"变成了"核心生产力"。我在为多家金融和零售企业做技术咨询时发现,传统API集成方式已经难以应对实时决策、个性…

2026/8/6 12:05:12

Java 数组所有创建方式

不管是基本类型数组(int、char、double),还是引用类型数组(String、自定义类、对象),语法规则完全一样,一共 4 种写法。以 int[] 和 String[] 举例演示。 方式 1:先分配长度&#xf…

2026/8/6 12:05:12

解决macOS TCC权限导致的iMessage机器人JSON解析错误

1. 问题现象与背景分析最近在调试基于openclaw框架开发的iMessage机器人时,遇到了一个棘手的崩溃问题。错误日志显示机器人因"permission"不是合法JSON而异常终止,具体报错信息为:openclaw llamap svr operator(): got exception: …

2026/8/6 13:10:15

深度学习VGG网络实战:从3x3卷积原理到PyTorch实现与迁移学习

1. 项目概述:从“头歌”到VGG的深度学习实战之旅最近在“头歌”平台上看到了一个关于VGG的实践项目,这让我想起了几年前自己刚接触深度学习和计算机视觉时,对着VGG论文和代码反复琢磨的日子。VGG网络,全称Visual Geometry Group&a…

2026/8/6 13:10:15

EtherCAT设备为什么使用Chip LAN

EtherCAT设备为什么使用Chip LAN传统现场总线时代,许多传感器、I/O模块和电机驱动器只需要低速通信接口。随着控制器性能提高,现场总线逐渐成为多轴同步和高速数据交换的瓶颈。EtherCAT把以太网通信进一步延伸到伺服驱动器、机器人关节和分布式I/O&#…

2026/8/6 13:05:15

泳道图实战指南:从流程可视化到高效协作

1. 泳道图:不只是画几条线那么简单 如果你在团队协作、流程梳理或者项目复盘时,感觉沟通起来像在“鸡同鸭讲”,或者总有人搞不清自己该在哪个环节做什么,那你大概率需要一个泳道图。这东西听起来有点专业,但说白了&…

2026/8/5 3:13:11

如何用免费工具突破游戏窗口限制:SRWE完整使用指南

如何用免费工具突破游戏窗口限制:SRWE完整使用指南 【免费下载链接】SRWE Simple Runtime Window Editor 项目地址: https://gitcode.com/gh_mirrors/sr/SRWE 你是否遇到过这样的困扰?想为心爱的游戏截图,却发现游戏不支持自定义分辨率…

2026/8/6 0:04:22

电力系统调度中的源荷不确定性建模与优化实践

1. 电力系统调度中的源荷不确定性挑战现代电力系统正面临前所未有的复杂性,其中源荷不确定性(Source-Load Uncertainty)已成为调度决策中最棘手的难题之一。我在参与某省级电网调度系统升级时,曾遇到风电预测误差导致日内调度计划…

2026/8/6 0:04:22

VGG-T3技术解析:3D重建速度的革命性突破

1. 项目概述:VGG-T3如何重新定义3D重建速度在计算机视觉领域,3D场景重建一直是个计算密集型任务。传统方法重建1000帧图像规模的场景往往需要数小时甚至更长时间,而英伟达最新发布的VGG-T3技术将这个时间压缩到了惊人的54秒。这个突破性进展来…

2026/8/6 0:04:22

深度解析旅游网站建设的意义及其对行业发展的深远影响与核心价值体现

在这个数字化浪潮席卷全球的今天,我们似乎已经忘记了,曾经有一段时间,人们想要去一个陌生的地方,只能靠在书桌前翻阅厚厚的旅游杂志,或者向刚从那里回来的朋友询问那些模糊不清的印象。那时候,“远方”是一个需要精打细算才能抵达的奢侈概念。而现在,只需要一部手机,轻…

2026/8/5 19:21:13

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/5 19:21:13

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/5 19:21:13

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…