ChartJS 在线图上覆盖2x轴

jgzswidk  于 2023-04-30  发布在  Chart.js
关注(0)|答案(1)|浏览(200)

以下是我的JSFiddle:https://jsfiddle.net/msuatp90/3/
基本上,我希望收入和过去的收入是重叠的,这样我就可以比较一个时期与前一个时期。它将始终为每个相同的刻度。
同样的事情的利润数据,我想利润和过去的利润重叠。
所有4个数据集每次都将具有完全相同的滴答数。但由于某种原因,它们并没有重叠,而是一个接一个地继续。
工具提示似乎工作正常。
下面是我现在拥有的完整代码:

let startGraph = function() {
  let canvas = document.getElementById('chart');
  let chart = new Chart(canvas.getContext('2d'), {
    type: 'line',
    data: {
      datasets: [{
          label: 'Revenue',
          data: {
            "2023-03-01": 250,
            "2023-03-02": 488,
            "2023-03-03": 358,
            "2023-03-04": 255,
            "2023-03-05": 895
          },
          borderColor: '#ff6384',
          xAxisID: 'x',
        },
        {
          label: 'Profit',
          data: {
            "2023-03-01": 125,
            "2023-03-02": 156,
            "2023-03-03": 195,
            "2023-03-04": 98,
            "2023-03-05": 466
          },
          borderColor: '#36a2eb',
          xAxisID: 'x',
        },
        {
          label: 'Past Revenue',
          data: {
            "2023-02-24": 280,
            "2023-02-25": 456,
            "2023-02-26": 665,
            "2023-02-27": 288,
            "2023-02-28": 499
          },
          borderColor: '#fa829b',
          xAxisID: 'x1',
        },
        {
          label: 'Past Profit',
          data: {
            "2023-02-24": 125,
            "2023-02-25": 198,
            "2023-02-26": 265,
            "2023-02-27": 101,
            "2023-02-28": 221
          },
          borderColor: '#76c1f5',
          xAxisID: 'x1',
        }
      ]
    },
    options: {
      elements: {
        point: {
          radius: 0,
          hoverRadius: 0,
          hitRadius: 3,
        },
        line: {
          borderWidth: 2,
        },
      },
      responsive: true,
      maintainAspectRatio: false,
      interaction: {
        intersect: false,
        mode: 'index',
      },
      stacked: false,
      scales: {
        y: {
          ticks: {
            display: true,
            beginAtZero: true,
          }
        },
        x: {
          position: 'bottom',
          ticks: {
            display: false,
          },
        },
        x1: {
          position: 'top',
          ticks: {
            display: false,
          },
          grid: {
            drawOnChartArea: false,
          },
        },
      },
      plugins: {
        legend: {
          display: true,
          position: 'bottom',
          labels: {
            boxWidth: 8,
            boxHeight: 8,
            useBorderRadius: true,
            borderRadius: 3,
            usePointStyle: false,
            pointStyleWidth: 0,
            padding: 7,
            font: {
              size: 11
            }
          }
        },
      },
    }
  });
}
3z6pesqy

3z6pesqy1#

如果启用xx1轴刻度,您将看到问题所在:两个x轴都是分类轴,而不是时间轴,这意味着日期字符串被视为简单字符串,而不被解释为日期。这可能对你有用,因为日期都是相同的间隔(1天),但它仍然是危险的,因为它们没有排序,也不能保证它们是有序的。
因此,为了解决这个问题并使图表显示更安全,我将解析日期并将其转换为以下形式的日期排序数组

[{x:timestamp1, y: value1}, {x: timestamp2, y: value2},...]

下面是一个针对date的函数:

function parseDateIndexed(data){
    return Object.entries(data).
        map(([s, f])=>({x: Date.parse(s), y: f, s})).
        sort(({x:t1},{x:t2})=>t1-t2);
}

我还在s下以字符串格式保存了原始日期,因为它在格式化时很有用,例如工具提示。
如果你不想显示日期,你可以使轴"linear",如下面的例子,其中唯一棘手的部分是格式化工具提示标题。同样的技术也可以应用于格式化轴标签,但是您也可以选择将x轴的类型声明为"time"并使用适配器,如chartjs-adapter-date-fns

function parseDateIndexed(data){
    return Object.entries(data).
    map(([s, f])=>({x: Date.parse(s), y: f, s})).
    sort(({x:t1},{x:t2})=>t1-t2);
}

let startGraph = function() {
    let canvas = document.getElementById('chart');
    let chart = new Chart(canvas.getContext('2d'), {
        type: 'line',
        data: {
            datasets: [{
                label: 'Revenue',
                data: parseDateIndexed({
                    "2023-03-01": 250,
                    "2023-03-02": 488,
                    "2023-03-03": 358,
                    "2023-03-04": 255,
                    "2023-03-05": 895
                }),
                borderColor: '#ff6384',
                xAxisID: 'x',
            },
                {
                    label: 'Profit',
                    data: parseDateIndexed({
                        "2023-03-01": 125,
                        "2023-03-02": 156,
                        "2023-03-03": 195,
                        "2023-03-04": 98,
                        "2023-03-05": 466
                    }),
                    borderColor: '#36a2eb',
                    xAxisID: 'x',
                },
                {
                    label: 'Past Revenue',
                    data: parseDateIndexed({
                        "2023-02-24": 280,
                        "2023-02-25": 456,
                        "2023-02-26": 665,
                        "2023-02-27": 288,
                        "2023-02-28": 499
                    }),
                    borderColor: '#fa829b',
                    xAxisID: 'x1',
                },
                {
                    label: 'Past Profit',
                    data: parseDateIndexed({
                        "2023-02-24": 125,
                        "2023-02-25": 198,
                        "2023-02-26": 265,
                        "2023-02-27": 101,
                        "2023-02-28": 221
                    }),
                    borderColor: '#76c1f5',
                    xAxisID: 'x1',
                }
            ]
        },
        options: {
            elements: {
                point: {
                    radius: 0,
                    hoverRadius: 0,
                    hitRadius: 3,
                },
                line: {
                    borderWidth: 2,
                },
            },
            responsive: true,
            maintainAspectRatio: false,
            interaction: {
                intersect: false,
                mode: 'index',
            },
            stacked: false,
            scales: {
                y: {
                    ticks: {
                        display: true,
                        beginAtZero: true,
                    }
                },
                x: {
                    type:"linear",
                    position: 'bottom',
                    ticks: {
                        display: false,
                    },
                },
                x1: {
                    type:"linear",
                    position: 'top',
                    ticks: {
                        display: false,
                    },
                    grid: {
                        drawOnChartArea: false,
                    },
                },
            },
            plugins: {
                tooltip:{
                    callbacks:{
                        title(items){
                            const dates = items.map(o=>o.raw.s);
                            const d1 = dates[0], d2 = dates[dates.length-1];
                            const ad = (d1 === d2) ? d1 : [d1, d2];
                            return ad.join(' / ')
                        }
                    }
                },
                legend: {
                    display: true,
                    position: 'bottom',
                    labels: {
                        boxWidth: 8,
                        boxHeight: 8,
                        useBorderRadius: true,
                        borderRadius: 3,
                        usePointStyle: false,
                        pointStyleWidth: 0,
                        padding: 7,
                        font: {
                            size: 11
                        }
                    }
                },
            },
        }
    });
}

document.addEventListener("DOMContentLoaded", function() {
    startGraph();
});
<canvas id="chart"></canvas>

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.1.2/chart.umd.js"
        integrity="sha512-t41WshQCxr9T3SWH3DBZoDnAT9gfVLtQS+NKO60fdAwScoB37rXtdxT/oKe986G0BFnP4mtGzXxuYpHrMoMJLA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

相关问题