news 2026/10/5 1:35:54

微信小程序Echarts中国地图加载指南:GeoJSON处理与性能优化

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
微信小程序Echarts中国地图加载指南:GeoJSON处理与性能优化

最近在做微信小程序的数据可视化项目,需要在首页展示一张中国地图,用来呈现各区域的业务数据分布情况。这个需求看着简单,真动手才发现坑不少——小程序环境和网页不一样,没有DOM节点,Echarts的好多用法都要换一套思路来写。这篇文章我把在小程序里用Echarts加载中国地图的完整步骤重新捋一遍,从组件引入、GeoJSON数据处理到option配置、交互联动,都给出能直接复制的代码和踩坑记录。

1. 整体思路:为什么在微信小程序里用Echarts画中国地图

1.1 需求场景与方案对比

小程序里做数据可视化,最常见的需求之一就是地图。业务上通常会把订单量、用户数、销售额这些指标按省份汇总,然后投到一张中国地图上,用颜色深浅表达数值大小。这种图放在数据大屏、管理后台、运营报表里都非常直观。

但在小程序里实现地图可视化,方案其实没有网页端那么随意。我梳理了一下,主流的选择主要有三种:

方案优点缺点
微信原生map组件系统级渲染,原生组件性能好,有marker、polyline、polygon内置底图样式固定,自定义绘制能力弱,不支持区域色块填充这种地图统计图
uCharts / F2等轻量图表库体积小,启动快,适合折线图柱状图地图支持很弱,F2的地图能力需要额外折腾,文档少
Echarts(echarts-for-weixin)生态成熟,地图Series、visualMap、markPoint都能用,社区案例多包体积大,canvas渲染性能要自己优化

Echarts在小程序里能用,靠的是官方和社区维护的echarts-for-weixin这个适配层。它把Echarts依赖的DOM操作封装成小程序canvas能理解的方式,然后用一套近乎原生的API来初始化图表。这意味着你在网页端写过的配置项、数据格式、交互事件,在小程序里基本都能复用,学习成本几乎为零。

1.2 小程序里Echarts的运行机制

网页端用Echarts,核心是echarts.init(document.getElementById('main')),因为浏览器能直接操作DOM。小程序不行,没有document,组件渲染靠的是canvas两层结构——一个离屏canvas负责绘制,一个展示canvas负责显示。echarts-for-weixin就干了这么一件事:把init方法的第一个参数从DOM节点换成小程序canvas实例,内部替你处理了坐标系、事件绑定、动画调度这些差异。

所以你会看到编写代码时,初始化变成了这样:

function initChart(canvas, width, height, dpr) { const chart = echarts.init(canvas, null, { width: width, height: height, devicePixelRatio: dpr }); canvas.setChart(chart); chart.setOption({...}); return chart; }

这里的canvas不是你在wxml里写死的那个<canvas>标签,而是ec-canvas组件通过ec属性回调给你的一个封装对象。这个封装对象内部维护了Echarts实例的完整生命周期,你只需要在回调里拿到它,然后正常setOption就行。

理解这一层,你才不会被各种报错搞晕。很多新手遇到"map is not defined"或者"canvas未初始化",其实就是没有搞清楚ec-canvas的初始化机制,或者把网页端直接echarts.init的代码搬过来用了。

1.3 实现地图渲染的完整链路

在小程序里用Echarts加载中国地图,整个流程可以拆成四段:

  1. 引入echarts-for-weixin组件到小程序项目,并完成页面级配置。
  2. 准备中国地图的GeoJSON数据(也就是省份边界经纬度数据)。
  3. 把GeoJSON注册为名为china的地图资源。
  4. 使用type: 'map'的series,配合data数据渲染出地图。

听起来不复杂,但每一段都有细节,尤其是GeoJSON的获取和注册方式,很多人在这块翻车。接下来我按顺序一步步拆开讲。

2. 环境准备:把echarts-for-weixin组件装进项目

2.1 获取echarts-for-weixin组件文件

第一步是拿到封装好的组件文件。Echarts官方仓库维护了一个微信小程序分支,核心文件就两个:

  • ec-canvas/ec-canvas.js:组件逻辑,负责canvas生命周期管理
  • ec-canvas/ec-canvas.wxml+ec-canvas.wxss+ec-canvas.json:组件模板和样式
  • ec-canvas/echarts.js:压缩后的Echarts核心库

拿到这些文件最稳的方式是直接去官方仓库下载对应版本,然后整个ec-canvas目录拷到你项目根目录下。如果你使用的微信开发者工具支持npm构建,也可以走npm流程安装对应包,但目录结构要大写自己核对,因为后续引用的路径一旦写错,编译期就会报"组件未找到"。

这里提醒一下:echarts.js这个文件体积不小,全量引入大约1MB左右。小程序主包有2MB限制,很多项目一开始就超了。后面第6章我会专门讲体积优化的办法。

2.2 在页面中注册并引用组件

假设你的项目结构是:

├── ec-canvas/ │ ├── ec-canvas.js │ ├── ec-canvas.json │ ├── ec-canvas.wxml │ ├── ec-canvas.wxss │ └── echarts.js ├── pages/ │ └── map/ │ ├── map.wxml │ ├── map.js │ ├── map.json │ └── map.wxss

你需要在map.json里声明使用这个组件:

{ "usingComponents": { "ec-canvas": "../../ec-canvas/ec-canvas" } }

然后在map.wxml里放一个容器,里面嵌入ec-canvas组件:

<view class="map-container"> <ec-canvas id="china-map" canvas-id="china-map" ec="{{ ec }}"></ec-canvas> </view>

这里的ec必须是一个包含onInit函数的对象,在map.js里定义:

import * as echarts from '../../ec-canvas/echarts'; function initChart(canvas, width, height, dpr) { const chart = echarts.init(canvas, null, { width: width, height: height, devicePixelRatio: dpr }); canvas.setChart(chart); chart.setOption({}); // 后续在这里填地图配置 return chart; } Page({ data: { ec: { onInit: initChart } } });

注意几个关键点。canvas-id不能和页面里其他canvas重复,否则真机上可能渲染错乱。ec对象不是响应式的,不需要在视图层做数据绑定,它只负责在组件初始化时把回调传进去。另外ec-canvas的高度高度由其外层容器决定,所以map-container必须给一个明确的宽度和高度,不能是0,否则图表不会显示。

2.3 组件初始化的细节与常见误区

ec-canvas组件支持两种初始化模式:一种是页面加载时就自动初始化,也就是上面这种ec.onInit的方式;另一种是懒加载,适合数据通过接口异步获取、需要手动控制加载时机的场景。懒加载要在组件上多加一个lazy-load属性,然后在需要的时候手动调用:

this.selectComponent('#china-map').init((canvas, width, height, dpr) => { const chart = echarts.init(canvas, null, { width: width, height: height, devicePixelRatio: dpr }); canvas.setChart(chart); this.chart = chart; return chart; });

两种模式二选一,不要混用。我见过有人又传了onInit又调用init,结果canvas初始化了两次,报There is a chart instance already initialized on the canvas的错。遇到这个报错,检查一下你是不是重复初始化了。

还有一点,开发者工具模拟器上一切正常、真机上白屏的问题,多半出在canvas类型上。现在是2024年了,新项目建议直接用小程序基础库支持的canvas 2D模式,也就是在ec-canvas组件上加type="2d",初始化方式略有差异,但渲染性能和清晰度都更好。如果触屏事件或者动画性能有要求,2D模式是首选。

3. 中国地图数据准备:GeoJSON获取与注册

3.1 GeoJSON是什么,Echarts为什么离不开它

Echarts的地图series本身不带任何地图边界数据。你要画中国地图,首先得告诉它中国的省份边界长什么样——这就是GeoJSON干的事。

GeoJSON是一种基于JSON的地理数据格式,里面用FeatureCollection组织多个区域。以中国地图为例,每个省就是一个Feature,它的geometry字段存了该省边界上所有点的经纬度坐标,properties里通常还带着省份名称和adcode编码。

{ "type": "FeatureCollection", "features": [ { "type": "Feature", "properties": { "name": "北京市", "adcode": 110000 }, "geometry": { "type": "MultiPolygon", "coordinates": [...] } } ] }

Echarts拿到这份数据后,内部会做一次坐标投影转换,把经纬度变成canvas上的xy像素坐标,然后根据你把name字段匹配到series的data里,决定每个区域填充什么颜色、响应什么事件。

所以GeoJSON是地图渲染的地基,地基不牢,后面全白搭。

3.2 获取中国地图GeoJSON的渠道

获取这份数据的渠道不少,但我实际操作下来最推荐的是阿里云DataV.GeoAtlas。它提供公开的中国及各省份GeoJSON服务,更新的频次也还行,而且已经帮你做过一些简化处理。

访问DataV.GeoAtlas页面后,在右侧有个"中国"的地图预览,可以直接下载一份完整的中国GeoJSON文件。下载下来的数据是标准GeoJSON格式,直接用就行。

如果你要的是省级下钻数据——比如点击"广东"再显示广东省各市的地图——DataV也提供每个省的独立GeoJSON,URL一般形如:

https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json

其中100000是中国的adcode,换成省份的adcode就能拿到对应省份的数据,比如广东的adcode是440000。

还有一点要注意:下载下来的GeoJSON,里面的properties.name可能是"北京市""广东省"这种带市/省后缀的,但你的业务数据里可能只写了"北京""广东"。Echarts的data匹配是基于name字段精确匹配的,所以要么在GeoJSON里做name映射,要么在series配置里用nameMap做别名转换:

series: [{ type: 'map', map: 'china', nameMap: { '北京市': '北京', '广东省': '广东' }, data: [ { name: '北京', value: 100 }, { name: '广东', value: 200 } ] }]

这种细节,业务数据一多,匹配不上时地图上就会全是空白,排查起来还挺隐蔽的。

3.3 本地引入GeoJSON的两种方式

拿到GeoJSON文件后,怎么在小程序里喂给Echarts,有两种常见做法。

第一种是把GeoJSON保存成china.js文件,放在项目里比如/utils/map/china.js路径下,然后用CommonJS导出:

module.exports = { "type": "FeatureCollection", "features": [...] };

在页面JS里引入并注册:

const chinaMap = require('../../utils/map/china.js'); echarts.registerMap('china', chinaMap);

这种方式的好处是不依赖网络请求,稳定、离线可用。缺点是文件本身有几百KB,会占用包体积。所以很多人会再对GeoJSON做简化(比如删除不必要的精度位数、简化边界坐标点数量),把几百KB压缩到100KB以内。

第二种是把GeoJSON放在服务器上,然后用wx.request请求:

wx.request({ url: 'https://your-domain.com/map/china.json', success(res) { echarts.registerMap('china', res.data); // 再 setOption } });

这种方式的优点是不占包体积,缺点是必须在微信公众平台配置request合法域名,而且每次进入地图页都要等网络请求完成,交互上会有一个白屏等待期。解决等待期的办法是:先用空白canvas占位,数据加载完再调用setOption,或者把GeoJSON缓存到本地存储。

考虑到小程序“包体积寸土寸金”的特点,我的建议是:如果只是展示一张中国地图,而且项目没有分包计划,那就用本地引入,但务必做坐标简化;如果地图数据会频繁更新,或者本身就要做省市两级下钻,那远程加载再加缓存方案更合适。

3.4 registerMap的调用时机与重复注册

echarts.registerMap必须在setOption之前调用,因为setOption里引用了map: 'china'时,Echarts会立刻去内存里寻找已经注册过的地图资源。如果没找到,界面不会报错,但series渲染出来是空白的,甚至连网格都看不到。

另外注意不要重复注册同一个地图名字。有些人的代码在onLoad里注册一次,initChart里又注册一次,控制台会打印一条"Map china already exists"的警告。虽然这种警告不影响运行,但说明你的代码里有重复执行的地方,还是理顺比较好。

4. 核心实现:配置option渲染中国地图

4.1 页面布局与canvas初始化

假设你已经把ec-canvas组件接入好了,wxml里有一个.map-container容器:

<view class="map-container"> <ec-canvas id="china-map" canvas-id="china-map" force-use-old-canvas="true" ec="{{ ec }}"></ec-canvas> </view>

对应wxss:

.map-container { width: 100%; height: 600rpx; padding: 20rpx; box-sizing: border-box; }

注意:height: 100%在页面里经常因为父容器高度没撑起来而变成0,所以最好给固定高度或rpx高度。调试时可以先写死600rpx,确认渲染正常后再换成你真正需要的布局方式。

4.2 一个完整可跑的地图option

在initChart里,填入下面这组配置,就能看到第一张中国地图:

function initChart(canvas, width, height, dpr) { const chart = echarts.init(canvas, null, { width: width, height: height, devicePixelRatio: dpr }); canvas.setChart(chart); const chinaMap = require('../../utils/map/china.js'); echarts.registerMap('china', chinaMap); chart.setOption({ tooltip: { trigger: 'item', formatter: function(params) { if (params.value) { return params.name + '<br/>数值:' + params.value; } return params.name; } }, visualMap: { min: 0, max: 1000, left: 20, bottom: 20, text: ['高', '低'], inRange: { color: ['#e0f3f8', '#74add1', '#4575b4'] } }, series: [{ type: 'map', map: 'china', roam: true, label: { show: true, fontSize: 10 }, data: [ { name: '北京', value: 100 }, { name: '上海', value: 200 }, { name: '广东', value: 500 }, { name: '四川', value: 300 } ] }] }); return chart; }

这个配置里,visualMap负责把数据值映射成颜色,数据库中值越大颜色越深。series.data里的name要和注册地图的properties.name匹配,匹配不上的区域不显示数据,颜色会变成灰色空白。roam: true允许用户在真机上通过手势缩放和拖动地图,做数据大屏时常开的选项。

运行起来,你应该能看到一张带省份边界、有颜色深浅的中国地图。到这里,最核心的步骤已经打通了。

4.3 异步数据下的延迟setOption

实际项目中,中国地图的轮廓数据可以本地引入,但业务数据(比如各省的销售额)通常需要通过接口异步获取。

做法是在initChart里先只渲染地图轮廓,然后等接口返回后,再调用chart.setOption更新数据。ec-canvas的onInit回调拿到chart实例后,你需要把它挂到this或页面实例上,方便后续更新。

Page({ data: { ec: { onInit: initChart } }, onLoad() { wx.request({ url: 'https://your-domain.com/api/province-data', success: (res) => { const data = res.data.map(item => ({ name: item.provinceName, value: item.value })); this.chart.setOption({ series: [{ data: data }] }); } }); } }); function initChart(canvas, width, height, dpr) { const chart = echarts.init(canvas, null, { width: width, height: height, devicePixelRatio: dpr }); canvas.setChart(chart); const chinaMap = require('../../utils/map/china.js'); echarts.registerMap('china', chinaMap); chart.setOption({ series: [{ type: 'map', map: 'china', roam: true, label: { show: true } }] }); // 挂到页面实例 const pages = getCurrentPages(); const currentPage = pages[pages.length - 1]; currentPage.chart = chart; return chart; }

这种方式的好处是页面秒开,地图轮廓先呈现,数据回来再局部更新,用户体验比较流畅。

4.4 数据格式对不上的排查思路

如果你发现某个省份始终不显示数据,先从这两个方向排查:

第一,看省份名是否完全一致。一个特别容易踩的坑是:GeoJSON里的name是"广西壮族自治区",业务数据里写的是"广西",Echarts明确不会做模糊匹配,必须完全相等。

第二,看数据是字符串还是数字。value字段如果传成了字符串,visualMap有可能不认,因为数值比较时需要数字类型。接口返回的字段经常是字符串,记得先Number()转一下。

value: Number(item.value)

这两个问题解决之后,90%的地图数据空白问题都能搞定。

5. 进阶交互:markPoint、tooltip与省份联动

5.1 在指定城市上打标记点(markPoint)

很多需求会在地图上再叠加一些关键城市标记,比如总部所在地、重点门店位置。实现方式有两种,看你想要的效果。

第一种是直接在map系列的markPoint里配置:

series: [{ type: 'map', map: 'china', markPoint: { symbol: 'pin', symbolSize: 22, label: { show: true, formatter: '{b}' }, data: [ { name: '北京', coord: [116.4, 39.9] }, { name: '广州', coord: [113.26, 23.13] } ] } }]

coord直接填城市的经纬度,Echarts会处理坐标映射。这种方案适合标记点数量不多、只是做静态展示的场景。

第二种是叠加一个独立的scatter散点系列:

series: [ { type: 'map', map: 'china', data: provinceData }, { type: 'scatter', coordinateSystem: 'geo', data: [ { name: '北京', value: [116.4, 39.9, 100] }, { name: '广州', value: [113.26, 23.13, 200] } ], symbolSize: function(val) { return val[2] / 50; } } ]

scatter系列的好处是可以利用symbolSize做气泡大小映射,视觉上更直观,还能把经纬度数据统一维护在一个数组里,后续做动态更新更方便。

很多人会纠结markPoint里的coord到底该填什么。记住一个原则:Echarts的map坐标系里,coord的数字顺序是[经度,纬度],不要倒过来写。这个顺序和你在高德地图、百度地图里看到的经纬度习惯一致,但如果你从某些地理转换函数里拿数据,很容易出现[纬度,经度]的反转,造成的现象就是标记点跑到海上去。

5.2 tooltip定制与事件绑定

tooltip是用户交互的第一入口。在小程序里,Echarts的tooltip是可以正常显示的,但有一点要注意:formatter函数内只能返回字符串,不能操作DOM,因为小程序环境本身就是无DOM的。

tooltip: { trigger: 'item', formatter: function(params) { if (params.seriesType === 'map') { return params.name + ':' + (params.value || 0); } if (params.seriesType === 'scatter') { return params.name + ',数值:' + (params.value[2] || 0); } return ''; } }

事件绑定方面,常规做法是:

chart.on('click', function(params) { console.log('点击了', params.name); });

但我实际在真机测试时发现,某些版本和iOS环境下,chart.on('click')对地图区域的点击事件不够稳定,尤其是地图被拖拽或缩放后,点击事件容易丢。一个更稳妥的替代方案是把click事件挂到底层zrender对象上:

chart.getZr().on('click', function(event) { const pixel = { x: event.offsetX, y: event.offsetY }; const point = chart.convertFromPixel({ seriesIndex: 0 }, pixel); // point 是经纬度数组,然后自己判断落在哪个省份内 });

不过convertFromPixel方案需要你自己维护省份边界判断,逻辑复杂一些。我的经验是:如果是静态地图、无roam交互,直接用chart.on('click')没问题;如果开了roam,最好用click加节流的方式,或者干脆把roam关掉,换成一键缩放按钮,交互更可控。

5.3 省份下钻的实现思路

地图下钻是高频需求:点广东省,跳转到一个展示广东各市地图的页面。

我的做法是把省地图GeoJSON也提前准备好,点击事件里用params.name拿到省份名,然后跳转页面,并把省份名作为参数传过去:

chart.on('click', function(params) { wx.navigateTo({ url: '/pages/province-map/province-map?province=' + encodeURIComponent(params.name) }); });

在省份地图页面,根据省份名找到对应的adcode,请求或加载对应省份的GeoJSON,注册成新的地图名,再正常渲染。整个逻辑和中国地图完全一致,区别只在数据源。

有一个体验上的细节要注意:如果用户点的是"南海诸岛"这种特殊区块,GeoJSON里通常会有一块表示南海诸岛的区域,name常常是"南海诸岛"或空字符串。跳转前最好做一个白名单过滤,否则用户点到海上没反应或跳到一个空白页,体验就很差。

if (['南海诸岛', ''].includes(params.name)) { return; }

5.4 项目使用uni-app或其他框架时的适配思路

热词里有不少人在搜uni-app微信小程序相关的内容。如果你是用uni-app开发,再在小程序端用Echarts,思路是类似的,但有几处适配需要注意。

uni-app 2.8.1之后,官方推荐使用renderjs配合echarts实现网页端类似的DOM渲染,这样能绕开小程序canvas的很多限制。不过在小程序端,renderjs实际上也是映射到canvas实现的。更通用的做法是继续使用ec-canvas组件,把它作为静态资源放到uni-app项目的wxcomponents目录下,然后在页面中通过usingComponents注册。

uni-app里很多人在H5端和App端用vue-echarts,而小程序端用echarts-for-weixin,这是两套写法。要统一的话,可以在页面组件里做一层封装:对外暴露同一个renderChart方法,内部判断运行环境,H5走DOM初始化,小程序走ec-canvas初始化。这样业务代码不用改,只是底层适配不同。

6. 常见问题排查与性能优化实录

6.1 常见问题速查表

下面这些是我在开发过程中实际遇到过的问题,以及对应的排查手段,整理成一张表,方便你对照使用。

问题现象根本原因解决办法
地图空白,只有灰色网格GeoJSON未注册,或map名字和注册名不一致检查echarts.registerMap('china', data)和series[0].map === 'china'
部分省份不显示数据颜色name匹配不上,或value是字符串核对省份名,用Number()转换数值
真机不渲染,模拟器正常canvas类型问题或基础库版本太低切换canvas 2D模式,升级基础库
tooltip不弹出ec-canvas封装导致的触摸事件冲突检查是否在canvas上叠加了遮罩层,尝试移除disableTouch之类的属性
iOS上拖动地图卡顿canvas性能不足,动画开销大关掉动画,animation: false,降低devicePixelRatio
地图初始渲染一闪而过初始化前容器尺寸为0给容器固定宽高,或用wx.createSelectorQuery获取实际尺寸后再init
报错mapView is not defined注册地图时数据格式错误确认GeoJSON是标准的FeatureCollection结构
页面切后台再回来白屏图表实例被销毁或canvas重建在onShow里重新初始化,或把option暂存后恢复

6.2 包体积优化与性能调优

前面提到echarts全量js体积不小,针对这个问题有三个常用手段。

第一,用自定义构建。Echarts官网的在线定制工具可以勾选你需要的模块,比如只保留地图、柱状图、折线图、散点图和visualMap相关模块,构建出来的echarts.min.js可以压到400KB以内。如果你的项目只用地图,甚至能压到更小。

第二,把地图数据做简化。GeoJSON里的坐标点通常非常密,很多精度位对显示没有影响。你可以用一些地图坐标简化工具,将坐标精度从6位小数降到2位小数,再删掉一些冗余点。我试过一个中国全量GeoJSON,从700KB压到200KB,视觉上几乎没有差异,写几个工具脚本一跑就行。

第三,使用分包。地图页在微信小程序里适合放进分包,因为地图数据体积大、打开频率低,分包可以显著降低主包加载压力。微信分包最大支持单分包2MB,整个分包不超过30MB,放一个地图页加echarts库绰绰有余。

性能方面,在地图上做大量动画是不推荐的,canvas在真机上的绘制能力有限。比如设置roam开启时,拖动和缩放的过程中如果tooltip频繁刷新,会明显卡顿。我的处理办法是:

tooltip: { confine: true, animation: false }, series: [{ type: 'map', roam: true, scaleLimit: { min: 1, max: 3 } }]

scaleLimit限制了缩放范围,避免用户拉到特别大导致渲染压力陡增;animation: false关掉tooltip动画,交互响应更快。

6.3 真机兼容性与iOS渲染注意事项

热词里反复出现iOS、渲染机制相关的关键词,这里集中说几个我在真机上的经验。

第一,iOS上canvas是WebGL还是2D的选择会影响性能。ec-canvas默认走2D canvas,在iOS上如果遇到加载卡顿,可以试试把devicePixelRatio传小一点,比如2,减少像素填充量。

const chart = echarts.init(canvas, null, { width: width, height: height, devicePixelRatio: 2 });

dpr过大会导致canvas的实际像素宽高非常大,内存和绘制压力都会成倍上升。

第二,地图上如果有大量的label,在iOS低端机(比如iPhone 8或更老)可能会出现文字重叠或模糊。解决方法是适当调大label.fontSize,或者在缩放级别较小时关掉label:

label: { show: true, formatter: function(params) { return params.name.length > 2 ? params.name.slice(0, 2) : params.name; } }

第三,如果页面包含原生组件(map、video、textarea等)和echarts canvas重叠,在iOS上原生组件会覆盖canvas,产生层级错乱。这是因为微信原生组件默认是独立同层渲染,普通cover-view和canvas都不一定能盖住它。解决办法是彻底避免让原生组件与图表重叠,或者在布局上让两者分开。

6.4 调试工具与断点定位技巧

在小程序里调试Echarts地图,比网页端麻烦的地方在于没有浏览器DevTools的Elements面板查看canvas内容。我习惯用这几个手段配合定位问题。

一是把echarts实例暴露到全局,在控制台直接执行chart.getOption()查看当前option是否正常,确认是否有重复设置、数据是否更新进去。

二是在registerMap后面打印一下注册的地图数据量:

console.log('map features:', chinaMap.features.length);

如果这里打印出来是0,说明GeoJSON加载失败,后面渲染必然空白。

三是用wx.setStorageSync缓存调试数据,这样模拟器或真机每次冷启动时,可以先从缓存里取数据,方便复现问题。

写在最后的一点经验

这套流程我前后在几个项目里反复用过,最大的感受是:微信小程序里用Echarts加载中国地图,本质上没有特别高深的技术难点,卡壳的地方几乎都在数据准备和canvas初始化上。GeoJSON格式不对、name不匹配、容器高度为0、初始化重复,这几个问题占了日常排查的八成以上。

我个人在实际项目中的习惯是,先把地图渲染做通,再叠加业务数据,最后才做交互效果。每一步验证通过再走下一步,而不是一次性写完一大段代码再回去找bug。地图渲染这种涉及数据、canvas、配置三方的功能,分层验证能省下大量调试时间。

还有一个建议:做好之后把整个地图页封装成一个通用组件,传入省份数据和配置项就能复用。我在两个项目之间迁移时,直接把组件拷过去改一下数据源就上线了,省了不少重复工作。

如果你后续还有地图下钻、自适应缩放、动态轮播高亮这些需求,底层思路都是一样的——先把GeoJSON数据和setOption之间的通路摸清楚,后面就是在option里加配置的问题了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/5 1:35:39

基于STM32F746VG与MR25H40CDF的MRAM工业存储方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/5 1:35:22

STM32驱动WS2812灯带:PWM+DMA实现高效无CPU占用方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/5 1:35:15

瑞萨RZN2L EtherCAT从站实战:从硬件设计到TwinCAT联调排障

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/5 1:34:11

MRAM在工业现场替代EEPROM和Flash的实战经验与dsPIC33EP配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/5 1:33:13

取石子游戏全解析:从巴什博弈到尼姆博弈与SG定理

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/5 1:32:22

Python + EasyTrader + 同花顺:5分钟搭建个人自动化交易机器人

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华