说实话,写前端这行当久了,真的会有一种深深的无力感。尤其是碰到 ECharts 这种看似简单实则坑爹的图表库。最近有个需求,要在 Geo 地图上实现“全部选中”的效果,就是用户点一下按钮,地图上所有的区域都高亮显示,或者都进入选中状态。这听起来是不是特别简单?Ctrl+A 嘛,或者遍历一下 series 里的 data 不就行了?
我当初也是这么想的,结果被现实狠狠打了一巴掌。
事情是这样的,老板急吼吼地要个 demo,说客户那边要求能一键全选所有省份进行数据对比。我心想,这还不简单?写个循环,把每个区域的 selected 属性设为 true 不就完事了?于是我一顿操作猛如虎,代码敲得飞起。结果一运行,好家伙,地图是亮了,但数据不对啊!而且更离谱的是,当我再次点击取消选中时,有些区域死活选不中,或者状态混乱得像一团乱麻。
我查了文档,翻遍了 GitHub 上的 issue,发现很多人都在问这个问题。有人说是因为 Geo 组件和 Series 的数据结构不一样,Geo 是独立的配置项,而 Series 里的 data 是另一回事。这就很让人头大。你想想,Geo 里的 regions 数组,每个对象里有个 name 属性,对应着地图上的区域。而 Series 里的 data 也是靠 name 来匹配的。你要是直接改 Geo 里的 selected 状态,图表可能根本不会重新渲染,或者渲染了但交互逻辑乱了。
后来我试了好几种方法,有的说用 dispatchAction,有的说直接操作 DOM。折腾了半天,终于找到了一个相对靠谱的法子。核心思路是:不要试图去修改 Geo 配置里的 regions 数组,因为 ECharts 内部对 Geo 的处理比较特殊,它更像是一个静态的地理信息层,而不是动态的数据层。真正的选中状态,其实是由 Series 里的 data 控制的。
所以,正确的姿势应该是这样的:你需要获取到当前 Series 里的所有 data,然后遍历这个数组,把每个 item 的 selected 属性设为 true。但是,这里有个大坑,就是 Geo 地图通常使用的是 scatter 或者 map 系列,而且往往配合着 visualMap 或者 tooltip 使用。如果你只是改了 selected,可能视觉上没变化,因为 ECharts 默认的高亮样式可能没生效。
我最后的解决方案是,在点击“全部选中”按钮时,先调用 chart.dispatchAction({ type: 'takeGlobalCursor', key: 'select', selectedMode: 'single' }) 这种操作不太对,应该是直接修改 option 里的 series[0].data。对,就是修改 data 数组。把每个 data 对象里的 selected 设为 true,然后调用 chart.setOption(option, true)。注意,setOption 的第二个参数一定要传 true,表示不合并,直接替换,这样才能确保状态重置。
但这还不够,因为 Geo 地图的选中效果,往往还涉及到 tooltip 的显示。如果你全选后,鼠标移上去,tooltip 显示的是第一个选中的区域,那体验也很差。所以,你可能还需要处理 tooltip 的逻辑,或者干脆在全选状态下隐藏 tooltip,或者显示一个汇总信息。
这个过程真的挺折磨人的。我甚至怀疑是不是自己版本不对,换了好几个 ECharts 版本,从 4.x 到 5.x,问题依旧。最后才发现,原来是因为我忽略了 Geo 的 map 属性。在 Geo 配置里,map 属性指定了地图类型,比如 'china'。而 Series 里的 seriesType 是 'map'。这两者必须对应起来。如果 Series 里用的是 scatter,那 Geo 的选中状态根本不会联动。
所以,总结一下,echarts geo全部选中 的关键在于:确保 Series 的类型是 map,并且正确修改 Series 中 data 的 selected 属性,而不是去动 Geo 的 regions。同时,别忘了调用 setOption 并传入 true 来强制刷新。
这玩意儿真的让人头大,文档里写得模棱两可,社区里的回答也是牛头不对马嘴。希望我这点经验能帮到同样被折磨的你。如果你还在为 echarts geo全部选中 这个问题发愁,不妨试试这个方法。要是还不行,那就只能去翻源码了,毕竟源码才是最诚实的。
别指望什么一键生成的代码能解决所有问题,前端这行,就是要在坑里打滚才能学会走路。加油吧,打工人。