数据可视化开发的时候,经常会用到饼图pie,那么轴标签一般必不可少,如何使用了像echarts等库,自带解决方案。
可是我们不一定会用库,像d3提供了很多基础svg绘制能力,label就需要自己绘制,这个时候就需要处理label防重叠。
网上相关的答案比较少,也都不智能,数据一旦异常聚集就会出现问题。
经过思考,下面给出一种比较容易实现,效果还不错的方案。
仔细想想,我们的难点在哪里。其实把饼图中心店为坐标原点,分割成数学上的四个象限的话,对于 第四个象限是很好做防重叠处理的,在第四个象限的数据,我们只需要按照顺序,判断下一个label的坐标y是否覆盖了前一个lable的y坐标,如果覆盖了,那么把当前lable的坐标往上移即可。
看下伪代码:
// 假如我们已经有了一组包含第四象限lable的group数据
/**
* 辅助迭代函数
* @param prev
* @param item
* @param i
*/
function handlePos(prev: GroupItem, item: GroupItem, i: number) {
if (i > 0) {
const { y: prevY } = prev.pointEnd;
const { y } = item.pointEnd;
const disY = y - prevY;
const isPositiveY =
item.quadrant === Quadrant.One || item.quadrant === Quadrant.Four;
if (
Math.abs(disY) < labelDy ||
(isPositiveY && disY >= 0) ||
(!isPositiveY && disY <= 0)
) {
if (isPositiveY) {
const tempY = (prevY < y ? prevY : y) - labelDy;
item.pointEnd.y = tempY;
} else {
const tempY = (prevY < y ? y : prevY) + labelDy;
item.pointEnd.y = tempY;
}
}
}
return item;
}
group.map((item, i) => {
return handlePos(group[i - 1], item, i);
});
这个处理完毕的label在第四象限内就 都是不重叠的了。
那么仔细想想 第一二三象限 和 第四象限的处理区别,我们会发现,在方向上第二象限和第四象限是一样的。难点是第一象限 和 第三象限我们需要对数据进行reverse反转处理,计算label坐标,完成之后再reverse反转回去进行绘制,不理解的认真思考一下。
下面是参考代码:
// 分割成四个象限数据
let groups: GroupItem[][] = new Array(4).fill(null);
labels.forEach((item) => {
const group = groups[item.quadrant] || [];
groups[item.quadrant] = group;
group.push(item);
});
groups = groups.map((group, index) => {
if (!group) return group;
if (index === Quadrant.Four || index === Quadrant.Two) {
group.map((item, i) => {
return handlePos(group[i - 1], item, i);
});
} else {
group = group
.reverse()
.map((item, i) => {
return handlePos(group[i - 1], item, i);
})
.reverse();
}
return group;
});
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。