用ECharts绘制UMAP散点图时,如何将系列标签置于聚类中心?
ECharts聚类散点图:将标签置于聚类中心的实现方案
问题背景
用ECharts绘制聚类散点图时,每个series对应一个聚类,当前代码仅将标签放在系列的第一个数据点上,需求是把每个系列的标签精准放在聚类的中心位置(x、y坐标的平均值)。数据集格式示例:['-4.03', '-1.99', '1.Normal.Gpr182.Stab2'],其中前两位是坐标,第三位是标签名。
解决方案:提前计算聚类中心,单独控制标签显示
核心是先算出每个聚类的中心坐标,再通过独立的系列或数据点来显示标签,避免和原散点数据混淆。
方法1:添加独立系列显示中心标签(推荐)
这种方法逻辑清晰,不修改原散点数据集,也不会干扰原系列的交互。
- 先计算所有聚类的中心坐标
假设你有存储各聚类数据的datasets数组,先遍历计算每个聚类的x、y平均值:
// 示例:datasets是包含所有聚类数据的数组 var datasets = [ [['-4.03', '-1.99', '1.Normal.Gpr182.Stab2'], ...], [['0.31', '5.25', '5.Irf1.Cxcl10'], ...], [['9.24', '-6.13', '8.Cycling.Mki67'], ...] ]; var clusterCenters = []; for (var i = 0; i < datasets.length; i++) { var dataList = datasets[i]; var sumX = 0, sumY = 0; // 遍历当前聚类的所有数据点,累加坐标值 for (var j = 0; j < dataList.length; j++) { sumX += parseFloat(dataList[j][0]); sumY += parseFloat(dataList[j][1]); } // 计算中心坐标,并存入数组 clusterCenters.push({ x: sumX / dataList.length, y: sumY / dataList.length, labelName: cell_type[i] // 直接用cell_type的名称作为标签 }); }
- 修改series生成逻辑
保留原散点系列,同时为每个聚类添加一个仅显示标签的“空散点”系列:
var series = []; for (var i = 0; i < cell_type.length; i++) { // 1. 原散点系列:关闭标签,只显示散点 series.push({ name: cell_type[i], type: "scatter", emphasis: { focus: "series", }, datasetIndex: i + 1, symbolSize: 2, encode: { x: "x", y: "y", }, label: { show: false } }); // 2. 中心标签系列:隐藏散点符号,只显示标签 series.push({ name: `${cell_type[i]}_center`, type: "scatter", symbolSize: 0, // 隐藏散点 data: [[clusterCenters[i].x, clusterCenters[i].y, clusterCenters[i].labelName]], label: { show: true, position: "top", color: "#000", fontSize: 10, formatter: (params) => params.data[2] }, emphasis: { disabled: true } // 关闭高亮,避免干扰原系列 }); }
方法2:在原数据集中添加中心数据点
如果不想新增系列,可以在原数据集末尾添加中心数据点,通过formatter和symbolSize控制仅显示该点的标签:
- 向数据集添加中心点
// 遍历每个数据集,添加中心点到末尾 for (var i = 0; i < datasets.length; i++) { var center = clusterCenters[i]; datasets[i].push([center.x, center.y, center.labelName]); }
- 修改原series的配置
var series = []; for (var i = 0; i < cell_type.length; i++) { series.push({ name: cell_type[i], label: { show: true, position: "top", color: "#000", fontSize: 10, formatter: function (params) { // 仅显示最后一个数据点(中心)的标签 if (params.dataIndex === params.seriesData.length - 1) { return params.data[2]; } return ""; }, }, type: "scatter", emphasis: { focus: "series", }, datasetIndex: i + 1, // 控制中心点的符号大小为0,隐藏它 symbolSize: function(params) { return params.dataIndex === params.seriesData.length - 1 ? 0 : 2; }, encode: { x: "x", y: "y", }, }); }
说明
- 方法1更适合复杂场景,标签和散点完全独立,不会互相干扰;
- 方法2更简洁,但需要修改原数据集,适合简单的可视化需求。
内容的提问来源于stack exchange,提问作者Bioinfotec
相关产品推荐
相关产品推荐

