如何在chart.js中将对数刻度分配给y轴?

8
var data1 = {
        labels: JSON.parse('<?php echo JSON_encode($bioc_months);?>'),
        datasets: [{
                fillColor: "rgba(220,220,220,0.5)",
                strokeColor: "rgba(220,220,220,1)",
                pointColor: "rgba(220,220,220,1)",
                pointStrokeColor: "#fff",
                data: 1000,
                900,
                90,
                200,
                1020
            }, {
                fillColor: "rgba(151,187,205,0.5)",
                strokeColor: "rgba(151,187,205,1)",
                pointColor: "rgba(151,187,205,1)",
                pointStrokeColor: "#fff",
                data: 600,
                456,
                20,
                2,
                900
            ]
        };

        var opt1 = {
            canvasBordersWidth: 3,
            canvasBordersColor: "#205081",
            scaleOverride: true,
            scaleSteps: 6,
            scaleStepWidth: log2,
            scaleStartValue: 0,
            scaleLabel: "<%=value%>",
            legend: true,
            inGraphDataShow: true,
            annotateDisplay: true,
            inGraphDataShow: false,
            annotateDisplay: true,
            animationEasing: "easeOutBounce",
            graphTitleFontSize: 18
        };

        var myBarChart1 = new Chart(ctx1).Bar(data1, opt1);

5
非常暴力的“问题”,其实只是一段代码。 - Alexis Paques
1
你应该考虑添加更多信息,而不仅仅是在这里发布代码。 - John Archer
3个回答

23

您可以按照以下方式将对数刻度分配给 y 轴:

yAxes: [{
    scaleLabel: {
        display: true,
        labelString: 'LABEL',
    },
    type: 'logarithmic',
    position: 'left',
    ticks: {
         min: 0.1, //minimum tick
         max: 1000, //maximum tick
         callback: function (value, index, values) {
             return Number(value.toString());//pass tick values as a string into Number function
         }
    },
    afterBuildTicks: function (chartObj) { //Build ticks labelling as per your need
        chartObj.ticks = [];
        chartObj.ticks.push(0.1);
        chartObj.ticks.push(1);
        chartObj.ticks.push(10);
        chartObj.ticks.push(100);
        chartObj.ticks.push(1000);
    }
}]

我认为你的回调方法有误。参数value是数字,应该返回一个string类型。这基本上允许你将值如1000000重命名为"1M"。如果您不想为该值设置标签,也可以返回null。根据我的测试,afterBuildTicks是多余的。(我甚至不确定它是否有效,因为在文档中无法检索到它)。话虽如此,没有它也能正常工作,你的其余答案对我帮助很大。无论如何,如果您不想让标签像“2e5”一样表示值如200000,则回调方法非常关键。 - bvdb
我只想说我最终使用了afterBuildTicks来动态生成日志数值,以适应不断变化的数据集所需的范围。我使用ticks回调将数字toLocaleString()'d,添加逗号以使大的十的倍数可读。所以,这并不是冗余的。 - Kyle Baker

14

正如@user2722127指出的那样,关键是将类型设置为"logarithmic"

如果你只关注这一点,那么你最终会得到科学格式下尴尬的标签(例如200000 = "2e5")。我个人更喜欢它们更接近人类的方式。 因此,回调方法实际上将numeric数据值转换为string标签值。

注意:回调不会针对数据集中的所有值进行调用。它只会针对自动生成的刻度进行调用。在我的情况下,这已经足够了。尽管如此,可能会有过多的标签。因此,为了限制标签数量,我只需返回所有不需要的标签值的null

yAxes: [{
    type: 'logarithmic',
    ticks: {
         min: 1,
         max: 1000000,
         callback: function (value, index, values) {
             if (value === 1000000) return "1M";
             if (value === 100000) return "100K";
             if (value === 10000) return "10K";
             if (value === 1000) return "1K";
             if (value === 100) return "100";
             if (value === 10) return "10";
             if (value === 1) return "1";
             return null;
         }
    }
}]

result

注意:上面的截图显示了一个有0刻度的图表,但事实上这是错误的。正如您可以在上面的源代码中看到的那样,我后来将最小值修改为1。我不得不这样做,因为在chart.js的后续版本中,图表实际上会严重混乱,并有时绘制在图表下方。这一切都是由于0刻度造成的。实际上,从数学的角度来看,对数尺度不能真正具有0刻度。因此,从1或0.001开始更有意义。但不能是0。

编辑:

以下并非必须,但可能会提高性能。

如果您想要更多控制创建的刻度,请提供一个 afterBuildTicks 属性。(这与 @user2722127 的回答非常相似。)在这个例子中,它只用不同的刻度替换了图表对象的刻度数组内容。

  afterBuildTicks = (chartObj) => {
      const ticks = [1, 10, 100, 1000, 10000, 100000, 1000000];
      chartObj.ticks.splice(0, chartObj.ticks.length);
      chartObj.ticks.push(...ticks);
  }
你只需要将此函数作为属性添加到yAxis元素中,连同其他属性一起添加即可。
yAxes: [{
    type,
    ticks,
    afterBuildTicks
}]

你的示例回调函数是否期望数据集中包含这些值?如果不是,那么很有可能会经常返回 null。 - bvj
1
@bvj,这已经在答案中了,但可能不够清晰。回调函数不是针对数据集的值调用的,而是针对您轴上的“刻度”调用的。如果您想要预过滤或仅设置自己的刻度,可以为yAxis提供一个额外的afterBuildTicks函数。 - bvdb
1
@bvj,我添加了一个示例。 - bvdb
1
来自未来的消息:我正在迁移到Highcharts:更少的代码,更多的功能,也更适用于Angular。 - bvdb

9

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接