ChartJS 如何使几个相交点的数据标签显示得更好?

piwo6bdm  于 2023-10-18  发布在  Chart.js
关注(0)|答案(1)|浏览(109)

不,我有一张折线图,上面有几条线。这些线在某些点上相交。我还使用chartjs-plugin-datalabels来标记图形上的点。
问题是:如果我在一个地方有几个来自不同线的点,它们的标签也显示在一个地方,这是不好的。我怎样才能使它们看起来好看和可读?
你可以在第二个图表中看到这个问题(用“2(...)”点):

在DOC中没有找到任何东西,我是JS的新手。希望能得到大家的帮助:)

ztigrdn8

ztigrdn81#

如果没有看到你的代码,我必须推断它看起来是什么样子,以及我将如何解决它。
好吧,我会:
1.迭代数据并查找交叉点

  • 为具有所需标签的交叉点创建“字典”
  • 为了创建交叉点的标签,我使用了一个换行符,但也可以使用任何其他分隔符,如逗号等。
  • 使用插件中的formatter函数设置交叉点的标签
    这里有一个演示,我将如何做到这一点:
  • 代码中有一些注解标记了重要部分。*
const data = {
    labels: ['1', '2', '3', '4', '5'], 
    datasets: [{
        label: 'DS1',
        data: [{x:1, y: 1, v:'d1'}, {x:2, y: 2, v:'d1'}, {x:3, y: 4, v:'d1'}, {x:4, y: 3, v:'d1'}], 
     }, {
        label: 'DS2',
        data: [
            {x:1, y: 1, v:'d2'}, {x:2, y: 2, v:'d3'}, {x:3, y: 2, v:'d2'}, {x:4, y: 2, v:'d2'}], 
     }, {
        label: 'DS3',
        data: [{x:1, y: 1, v:'d3'}, {x:2, y: 2, v:'d3'}, {x:3, y: 5, v:'d3'}, {x:4, y: 5, v:'d3'}], 
     }],
};

// Helper to get all values into on array
let flatDatalist = data.datasets.map( entry => entry.data).flat();

// find all overlapping points
let overlappingEntries = flatDatalist.filter( (entry, index )=>{
    return flatDatalist.some((entryInner, indexInner) => index != indexInner && entry.x == entryInner.x && entry.y == entryInner.y)
})

// create an Array with new formated label for overlapping labels
let labelsForOverlappingEntries = overlappingEntries.reduce((prev, curr) => {
    let key = `${curr.x}__${curr.y}`;
    
    if(!prev[key]){
        prev[key] = `${data.labels[curr.x]}:${curr.v}`;
    } else {
          prev[key] = `${prev[key]}\n${data.labels[curr.x]}:${curr.v}`;
    }
    
    return prev;
 }, {});

const config = {
    type: 'line',
    data: data,
    plugins:[ChartDataLabels],
    options: {
        scales: {
          y: {
            min: 0,
            max: 6,
          }
        },
        maintainAspectRatio: false,
        plugins: {
          datalabels: {
            align: 'end',
            anchor: 'end',
            offset: -1,
            formatter: function(v, ctx){
              // get a multiline label when needed
              let key = `${v.x}__${v.y}`;
              if(labelsForOverlappingEntries[key]){
                return labelsForOverlappingEntries[key];
              }
              return ctx.chart.data.labels[ctx.dataIndex] + ': '+ v.v;
            },
          }
        }
    }
};

new Chart(
    document.getElementById('chart'),
    config
);
<script src="//cdn.jsdelivr.net/npm/chart.js"></script>  
<script src="
https://cdn.jsdelivr.net/npm/[email protected]/dist/chartjs-plugin-datalabels.min.js
"></script>
<div class="chart" style="height:184px; width:350px;">
    <canvas  id="chart" ></canvas>
</div>
  • 免责声明**我不确定这是否是最好的方法,它可能有点过度设计。尽管如此,它还是有效的,我希望你能使用它,或者至少它能帮助你找到自己的路。

相关问题