【问题标题】:ChartJS New Lines '\n' in X axis Labels or Displaying More Information Around Chart or Tooltip with ChartJS V2ChartJS X 轴标签中的新行 '\n' 或使用 ChartJS V2 在图表或工具提示周围显示更多信息
【发布时间】:2020-12-22 04:42:29
【问题描述】:

我正在使用 chart.js (V2) 来尝试构建一个条形图,该条形图向用户提供更多信息,而无需将鼠标悬停在或单击任何位置。我提供了两个示例来说明我希望如何编辑图表。

Two edited versions of what I hope to achieve

可以看出,我希望在(某处)标签之外放置一些额外的信息。我曾希望通过在标签中添加“\n”,我可能能够得到我正在寻找的类似于选项 A 的内容。

提供了一些编辑过的代码:

var barChartData = {

        labels: playerNames,
        datasets: [{
            label: 'Actual Score/Hour',
            backgroundColor: "rgba(0, 128, 0,0.5)",
            data: playerScores
          }, {
            label: 'Expected Score/Hour',
            backgroundColor: "rgba(255,0,0,0.5)",
            data: playerExpected
        }]
    };
function open_win(linktosite) {
           window.open(linktosite)
      }
        canvas.onclick = function(evt){
            var activePoints = myBar.getElementsAtEvent(evt);
            console.log(activePoints);
            linktosite = 'https://www.mytestsite.com/' + activePoints[1]['_model']['label'];
            open_win(linktosite);
}; 
window.onload = function() {
        var ctx = document.getElementById("canvas").getContext("2d");
        window.myBar = new Chart(ctx, {
            type: 'bar',
            data: barChartData,
            options: {
                title:{
                    display:true,
                    text:"Player Expected and Actual Score per Hour"
                },
                tooltips: {
                    mode: 'label'
                },
                responsive: true,
                scales: {
                    xAxes: [{
                        stacked: false,
                    }],
                    yAxes: [{
                        stacked: false
                    }]
                },
                animation: {
                    onComplete: function () {
                        var ctx = this.chart.ctx;
                        ctx.textAlign = "center";
                        Chart.helpers.each(this.data.datasets.forEach(function (dataset) {

                            Chart.helpers.each(dataset.metaData.forEach(function (bar, index) {
                                // console.log("printing bar" + bar);
                                ctx.fillText(dataset.data[index], bar._model.x, bar._model.y - 10);
                                }),this)
                                }),this);
                    }
                }
            }
        });
        // Chart.helpers.each(myBar.getDatasetMeta(0).data, function(rectangle, index) {
        // rectangle.draw = function() {
        //     myBar.chart.ctx.setLineDash([5, 5]);
        //     Chart.elements.Rectangle.prototype.draw.apply(this, arguments);
        //     }
        // }, null);            
    };

在这一点上,我对在栏的任何位置都有额外数据感到满意。任何帮助,将不胜感激。谢谢~

【问题讨论】:

    标签: javascript chart.js


    【解决方案1】:

    Chart.js v2.1.5 允许使用嵌套数组的多行标签(v2.5.0 修复了雷达图):

    ...
    data: {
        labels: [["Jake", "Active: 2 hrs", "Score: 1", "Expected: 127", "Attempts: 4"], 
                 ["Matt", "Active: 2 hrs", "Score: 4", "Expected: 36", "Attempts: 4"]],
        ...
    

    但是,这确实意味着您必须预先计算标签值。

    【讨论】:

      【解决方案2】:

      var config = {
        type: 'line',
        data: {
          labels: [["January","First Month","Jellyfish","30 of them"], ["February","Second Month","Foxes","20 of them"], ["March","Third Month","Mosquitoes","None of them"], "April", "May", "June", "July"],
          datasets: [{
            label: "My First dataset",
            data: [65, 40, 80, 81, 56, 85, 45],
            backgroundColor: "rgba(255,99,132,0.2)",
          }, {
            label: "My Second dataset",
            data: [40, 80, 21, 56, 85, 45, 65],
            backgroundColor: "rgba(99,255,132,0.2)",
          }]
        },
        scales : {
            xAxes : [{
                gridLines : {
                    display : false,
                    lineWidth: 1,
                    zeroLineWidth: 1,
                    zeroLineColor: '#666666',
                    drawTicks: false
                },
                ticks: {
                    display:true,
                    stepSize: 0,
                    min: 0,
                    autoSkip: false,
                    fontSize: 11,
                    padding: 12
                }
            }],
            yAxes: [{
                ticks: {
                    padding: 5
                },
                gridLines : {
                    display : true,
                    lineWidth: 1,
                    zeroLineWidth: 2,
                    zeroLineColor: '#666666'
                }
            }]
        },
                          spanGaps: true,
                          responsive: true,
                          maintainAspectRatio: true
      };
      
      var ctx = document.getElementById("myChart").getContext("2d");
      new Chart(ctx, config);
      <div class="myChart">
      <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.js"></script>
      
      <canvas id="myChart"></canvas>
                </div>

      如果标签是数组而不是字符串,即 [["June","2015"], "July"],则每个元素都被视为单独的行。进行适当的计算以确定正确的高度和宽度,并且仍然支持旋转。

      使用 charJS 版本 2.7.2 这也适用于https://github.com/jtblin/angular-chart.js

      【讨论】:

      • 你知道任何改变下一行之间距离的选项:JanuaryFirst Month?我使用fontSize: 16,所以这个距离对于我的情况来说太大了,但我无法改变它。
      • @kris_IV 你有没有想过这个问题?现在正在为此苦苦挣扎
      • @AdamMoisa 最后我创建了这个库的一个分支,因为我需要更多然后配置允许我。所以我直接在库中进行所有更改
      • 你能简单地解释一下你是如何让这个特定功能干净利落地工作的吗?真的很难过
      • 请参阅jsfiddle.net/Abeeee/ugn3x52e,了解使用过时的 x 轴的可调整大小的工作示例,该示例使用数组解决方案和刻度回调来查看 [猜测] 有多少可用空间。
      【解决方案3】:

      如果您使用的是 Chart.js v2.7.1,上述解决方案可能不起作用。

      实际上对我们有用的解决方案是在dataoptions 级别添加一个小的plugin

      const config = {
        type: 'bar',
        data: {
          // ...
        },
        options: {
          // ...
        },
        plugins: [{
          beforeInit: function (chart) {
            chart.data.labels.forEach(function (label, index, labelsArr) {
              if (/\n/.test(label)) {
                labelsArr[index] = label.split(/\n/)
              }
            })
          }
        }]
      };
      

      有关如何解决此问题的完整说明,请参见 here

      【讨论】:

      【解决方案4】:

      使用 Chart.js v2.1,您可以编写一个图表插件来做到这一点


      预览


      脚本

      Chart.pluginService.register({
          beforeInit: function (chart) {
              var hasWrappedTicks = chart.config.data.labels.some(function (label) {
                  return label.indexOf('\n') !== -1;
              });
      
              if (hasWrappedTicks) {
                  // figure out how many lines we need - use fontsize as the height of one line
                  var tickFontSize = Chart.helpers.getValueOrDefault(chart.options.scales.xAxes[0].ticks.fontSize, Chart.defaults.global.defaultFontSize);
                  var maxLines = chart.config.data.labels.reduce(function (maxLines, label) {
                      return Math.max(maxLines, label.split('\n').length);
                  }, 0);
                  var height = (tickFontSize + 2) * maxLines + (chart.options.scales.xAxes[0].ticks.padding || 0);
      
                  // insert a dummy box at the bottom - to reserve space for the labels
                  Chart.layoutService.addBox(chart, {
                      draw: Chart.helpers.noop,
                      isHorizontal: function () {
                          return true;
                      },
                      update: function () {
                          return {
                              height: this.height
                          };
                      },
                      height: height,
                      options: {
                          position: 'bottom',
                          fullWidth: 1,
                      }
                  });
      
                  // turn off x axis ticks since we are managing it ourselves
                  chart.options = Chart.helpers.configMerge(chart.options, {
                      scales: {
                          xAxes: [{
                              ticks: {
                                  display: false,
                                  // set the fontSize to 0 so that extra labels are not forced on the right side
                                  fontSize: 0
                              }
                          }]
                      }
                  });
      
                  chart.hasWrappedTicks = {
                      tickFontSize: tickFontSize
                  };
              }
          },
          afterDraw: function (chart) {
              if (chart.hasWrappedTicks) {
                  // draw the labels and we are done!
                  chart.chart.ctx.save();
                  var tickFontSize = chart.hasWrappedTicks.tickFontSize;
                  var tickFontStyle = Chart.helpers.getValueOrDefault(chart.options.scales.xAxes[0].ticks.fontStyle, Chart.defaults.global.defaultFontStyle);
                  var tickFontFamily = Chart.helpers.getValueOrDefault(chart.options.scales.xAxes[0].ticks.fontFamily, Chart.defaults.global.defaultFontFamily);
                  var tickLabelFont = Chart.helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);
                  chart.chart.ctx.font = tickLabelFont;
                  chart.chart.ctx.textAlign = 'center';
                  var tickFontColor = Chart.helpers.getValueOrDefault(chart.options.scales.xAxes[0].fontColor, Chart.defaults.global.defaultFontColor);
                  chart.chart.ctx.fillStyle = tickFontColor;
      
                  var meta = chart.getDatasetMeta(0);
                  var xScale = chart.scales[meta.xAxisID];
                  var yScale = chart.scales[meta.yAxisID];
      
                  chart.config.data.labels.forEach(function (label, i) {
                      label.split('\n').forEach(function (line, j) {
                          chart.chart.ctx.fillText(line, xScale.getPixelForTick(i + 0.5), (chart.options.scales.xAxes[0].ticks.padding || 0) + yScale.getPixelForValue(yScale.min) +
                              // move j lines down
                              j * (chart.hasWrappedTicks.tickFontSize + 2));
                      });
                  });
      
                  chart.chart.ctx.restore();
              }
          }
      });
      

      然后

      ...
      data: {
          labels: ["January\nFirst Month\nJellyfish\n30 of them", "February\nSecond Month\nFoxes\n20 of them", "March\nThird Month\nMosquitoes\nNone of them", "April", "May", "June", "July"],
               ...
      

      注意 - 我们假设一行的最大内容将适合刻度之间(即不需要旋转逻辑。我相信也可以合并旋转逻辑,但会稍微复杂一点)

      您应该将工具提示格式化为不显示 x 轴标签,或将其格式化为显示较短版本的标签。


      小提琴 - http://jsfiddle.net/m0q03wpy/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多