Chart JS,为不同的数据集选择不同的Y轴

时间:2017-11-10 16:48:23

标签: javascript chart.js

我的图表Codepen Example上有一个多Y轴。我想知道用户是否可以选择他/她想要在哪个y轴上的数据集? 有没有办法显示哪些数据当前正在使用哪个Y轴,用户是否可以选择将数据更改为不同的轴(左或右),如果他们喜欢图例?



Chart.defaults.global.elements.line.fill = false;

  var barChartData = {
  labels: [1510332261000, 1510332473000, 1510332489000, 1510332726000, 1510332777000, 1510332778000, 1510332958000, 1510333050000, 1510333131000, 1510333389000, 1510333476000, 1510333493000, 1510333588000, 1510333604000, 1510333664000, 1510333668000, 1510333758000, 1510333801000, 1510333820000, 1510333821000, 1510333878000, 1510333928000],
  datasets: [{
  type: 'line',
  label: 'a (F)',
  id: "y-axis-0",
  backgroundColor: "rgba(217,83,79,0.75)",
  data: [70, 72, 73, 73, 75, 50, 50, 40, 40, 45, 70, 73, 70, 73, 73, 73, 74, 73, 73, 73]
}, {
  type: 'line',
  label: 'b (V)',
  id: "y-axis-0",
  backgroundColor: "rgba(92,184,92,0.75)",
  data: [12.9, 17.9, 15.9, 17.9, 17.9, 17.9, 15.9, 17.9, 15.8, 17.8, 16.8, 17.8, 17.9, 17.9, 17.8, 17.8, 19.8, 17.9, 17.8, 20.8]
}, {
  type: 'line',
  label: 'c (%)',
  id: "y-axis-0",
  backgroundColor: "rgba(51,51,51,0.5)",
  data: [30, 30, 50, 30, 20, 10, 30, 40, 30, 50, 30, 70, 30, 50, 30, 80, 90, 30, 30, 30]
}, {
  type: 'line',
  label: 'd (AH)',
  id: "y-axis-1",
  backgroundColor: "rgba(151,187,205,0.5)",
  data: [10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6]
  }]
};


var ctx = document.getElementById("myChart");
// allocate and initialize a chart
var ch = new Chart(ctx, {
  type: 'bar',
  data: barChartData,
  options: {
    title: {
      display: true,
      text: "Chart.js"
    },
    tooltips: {
       mode: 'label'
    },
    responsive: true,
    scales: {
      xAxes: [{
        stacked: true
      }],
      yAxes: [{
        position: "left",
        id: "y-axis-0",
      }, {
        position: "right",
        id: "y-axis-1",
      }]
    }
  }
});

.myChartDiv {
  max-width: 600px;
  max-height: 400px;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.min.js"></script>
<html>
  <body>
    <div class="myChartDiv">
      <canvas id="myChart" width="600" height="400"></canvas>
    </div>
  </body>
</html>
&#13;
&#13;
&#13;

更新

我将图例自定义为this,并使用Ahmed 's suggestion code来修正Y轴刻度。我还在更新中添加了Ahmed's y axis code,但不知何故,它仍然没有像我预期的那样工作。 以下是我刚刚更新的new codepen

1 个答案:

答案 0 :(得分:1)

您使用ext barChartData.datasets[]的所有内容的拳头,但您应该使用id代替。给予yAxisID对图表没有影响。这是以下文档:http://www.chartjs.org/docs/latest/charts/line.html#dataset-properties

现在进入您要求的内容,您可以在图例中添加点击处理程序,以便在点击时在轴之间切换,以下是此示例:

  

使用新代码:https://codepen.io/anon/pen/ooZMwG?editors=0010

打开你的代码

id设置为此函数:

options.legend.onClick

**更新:**

基于您的新codepen,以下是一些可以提供帮助的内容:

我已向my answer添加了新更新,以便为图表中的所有Y轴添加offfset。使用它代替笔中的内容。

然后将您的function(e, legendItem) { var index = legendItem.datasetIndex; var ci = this.chart; var axisIds = [] var yAxes = ci.options.scales.yAxes; for (var i = 0; i < yAxes.length; i++) { // loop over the registered yAxes yAxes[i].gridLines.color = "rgba(0,0,0,0.1)"; // reset all scale gridlines to default axisIds.push(yAxes[i].id) // get all yAxes ids } var meta = ci.getDatasetMeta(index); var currentAxisId = meta.yAxisID var currentAxisIdIndex = axisIds.indexOf(currentAxisId); var newAxisIdIndex; // basically get the next axis id in the array, if the last one, get the first (circular) if (currentAxisIdIndex == axisIds.length - 1) newAxisIdIndex = 0; else newAxisIdIndex = currentAxisIdIndex + 1; var newAxisId = axisIds[newAxisIdIndex]; meta.yAxisID = newAxisId // set the new axis id to the next one in the array axis = ci.scales[newAxisId]; axis.options.gridLines.color = "rgba(0,0,0,1)"; // change lines color of the new axes ci.update(); // update chart } 更新为以下内容,并确保您的图例HTML容器具有ID:changeLeftRightY

legend

以下是codepen with the code result *我对您的部分代码进行了一些更改,以便于阅读。

如果更改或删除了该代码集,则以下是完整代码

changeLeftRightY = function(e, index) {
            //console.log("-- " + data.datasets[index].yAxisID)
            var ci = e.view.ch;
            var axisIds = []
            var yAxes = ci.options.scales.yAxes;
            for (var i = 0; i < yAxes.length; i++) { // loop over the registered yAxes
                yAxes[i].gridLines.color = "rgba(0,0,0,0.1)"; // reset all scale gridlines to default
                axisIds.push(yAxes[i].id) // get all yAxes ids
            }
            var meta = ci.getDatasetMeta(index);
            var currentAxisId = meta.yAxisID
            var currentAxisIdIndex = axisIds.indexOf(currentAxisId);
            var newAxisIdIndex;
            // basically get the next axis id in the array, if the last one, get the first (circular)
            if (currentAxisIdIndex == axisIds.length - 1) newAxisIdIndex = 0;
            else newAxisIdIndex = currentAxisIdIndex + 1;

            var newAxisId = axisIds[newAxisIdIndex];
            meta.yAxisID = newAxisId // set the new axis id to the next one in the array

            axis = ci.scales[newAxisId];
            axis.options.gridLines.color = "rgba(0,0,0,1)"; // change lines color of the new axes
            document.getElementById('legend').innerHTML = ci.generateLegend();

            ci.update()
        }

CSS:

// set default no fill beneath the line
Chart.defaults.global.elements.line.fill = false;
// Define a plugin to provide data labels
Chart.pluginService.register({
    beforeUpdate: function(chart){
      console.log("beforeUpdate");
      // get custom defined offset
      var offset = chart.options.customOffset;
      // exisit gracefully if offset not defined or less than 0
      if(!offset || offset < 0) return;
      var yAxes = chart.options.scales.yAxes;
      for(var i=0; i<yAxes.length; i++){
        var axis = yAxes[i];
        var datasets = chart.data.datasets;
        var max = Number.MIN_VALUE;
        var min = Number.MAX_VALUE;
        var datasetsOnAxis = [];

        for(var j=0; j<datasets.length; j++){ // add datasets for this axes to datasetsOnAxis
          var dataset = datasets[j];
          var meta = chart.getDatasetMeta(j);
          if  (meta.yAxisID === axis.id) datasetsOnAxis.push(dataset); 
        }

        for(var k=0; k<datasetsOnAxis.length; k++){
          var dataset = datasetsOnAxis[k]
          var newMax = Math.max.apply(null, dataset.data);
          var newMin = Math.min.apply(null, dataset.data);
          max = newMax > max ? newMax : max;
          min = newMin > min ? min : newMin;
        }
        axis.ticks.max = max + offset;
        axis.ticks.min = min - offset;   
      }
    }
});

var barChartData = {
  labels: [1510332261000, 1510332473000, 1510332489000, 1510332726000, 1510332777000, 1510332778000, 1510332958000, 1510333050000, 1510333131000, 1510333389000, 1510333476000, 1510333493000, 1510333588000, 1510333604000, 1510333664000, 1510333668000, 1510333758000, 1510333801000, 1510333820000, 1510333821000, 1510333878000, 1510333928000],
  datasets: [{
    type: 'line',
    label: 'a (F)',
    yAxisID: "y-axis-0",
    backgroundColor: "rgba(217,83,79,0.75)",
    data: [70, 72, 73, 73, 75, 50, 50, 40, 40, 45, 70, 73, 70, 73, 73, 73, 74, 73, 73, 73]
  }, {
    type: 'line',
    label: 'b (V)',
    yAxisID: "y-axis-0",
    backgroundColor: "rgba(92,184,92,0.75)",
    data: [12.9, 17.9, 15.9, 17.9, 17.9, 17.9, 15.9, 17.9, 15.8, 17.8, 16.8, 17.8, 17.9, 17.9, 17.8, 17.8, 19.8, 17.9, 17.8, 20.8]
  }, {
    type: 'line',
    label: 'c (%)',
    yAxisID: "y-axis-0",
    backgroundColor: "rgba(51,51,51,0.5)",
    data: [30, 30, 50, 30, 20, 10, 30, 40, 30, 50, 30, 70, 30, 50, 30, 80, 90, 30, 30, 30]
  }, {
    type: 'line',
    label: 'd (AH)',
    yAxisID: "y-axis-1",
    backgroundColor: "rgba(151,187,205,0.5)",
    data: [10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6]
  }]
};

var options = {
  title: {
      display: true,
      text: "Chart.js"
    },
  legendCallback: function (chart) {
                console.log('legendCallback');
                var legendHtml = [];
                legendHtml.push('<div id="legend">');
                for (var i = 0; i < chart.data.datasets.length; i++) {
                    var meta = ch.getDatasetMeta(i);
                    var yAxis = meta.yAxisID =='y-axis-0' ? "Left Axis" : "Right Axis"

                    if (chart.data.datasets[i].label) {
                        var datasetIndex = chart.legend.legendItems[i].datasetIndex
                        var color = chart.data.datasets[i].backgroundColor;
                        var label = chart.data.datasets[i].label;
                        legendHtml.push(
                          '<div class="lgnd-item-container">'+
                            '<input class="lgnd-ckeckbox" type="checkbox" checked '+
                                    'onclick="updateDataset(event, '+datasetIndex+')"/>'+
                            '<div class="lgnd-square" style="background-color:'+color+'"></div>'+
                            '<div class="lgnd-label">'+label+' '+yAxis+'</div>'+
                            '<input class="lgnd-btn" type="button" value="Change" onclick="changeLeftRightY(event,'+datasetIndex +')"></input>'+
                          '</div>');
                    }
                }
                legendHtml.push('</div>');

                return legendHtml.join("");
            },
            legend:{
              display:false
            },
            customOffset: 2,
            responsive: true,
            tooltips: {
                mode: 'label',
                position: 'nearest'
            },
  scales: {
      xAxes: [{
        stacked: true
      }],
      yAxes: [{
        position: "left",
        id: "y-axis-0",
      }, {
        position: "right",
        id: "y-axis-1",
      }]
    }

}

// Show/hide chart by click legend
updateDataset = function (e, datasetIndex) {
            var index = datasetIndex;
            var ci = e.view.ch;
            var meta = ci.getDatasetMeta(index);
            // See controller.isDatasetVisible comment
            meta.hidden = meta.hidden === null ? !ci.data.datasets[index].hidden : null;
            // We hid a dataset ... rerender the chart
            ci.update();
        };

var ctx = document.getElementById("myChart");
// allocate and initialize a chart
window.ch = new Chart(ctx, {
  type: 'line',
  data: barChartData,
  options: options

});
document.getElementById("chartLegend").innerHTML = ch.generateLegend();

changeLeftRightY = function(e, index) {
            //console.log("-- " + data.datasets[index].yAxisID)
            var ci = e.view.ch;
            var axisIds = []
            var yAxes = ci.options.scales.yAxes;
            for (var i = 0; i < yAxes.length; i++) { // loop over the registered yAxes
                yAxes[i].gridLines.color = "rgba(0,0,0,0.1)"; // reset all scale gridlines to default
                axisIds.push(yAxes[i].id) // get all yAxes ids
            }
            var meta = ci.getDatasetMeta(index);
            var currentAxisId = meta.yAxisID
            var currentAxisIdIndex = axisIds.indexOf(currentAxisId);
            var newAxisIdIndex;
            // basically get the next axis id in the array, if the last one, get the first (circular)
            if (currentAxisIdIndex == axisIds.length - 1) newAxisIdIndex = 0;
            else newAxisIdIndex = currentAxisIdIndex + 1;

            var newAxisId = axisIds[newAxisIdIndex];
            meta.yAxisID = newAxisId // set the new axis id to the next one in the array

            axis = ci.scales[newAxisId];
            axis.options.gridLines.color = "rgba(0,0,0,1)"; // change lines color of the new axes
            document.getElementById('legend').innerHTML = ci.generateLegend();

            ci.update()
        }

HTML:

.myChartDiv {
  max-width: 600px;
  max-height: 400px;
}
.lgnd-square {
  float: left;
  height: 20px;
  width:20px;
  overflow:hidden; 
  margin: 5px;
}

.lgnd-ckeckbox{
  float:left;
  margin: 10px;
}
.lgnd-btn{
  float: left;
  margin: 5px;
}
.lgnd-item-container{
  width: 300px;
  height: 40px;
}
.lgnd-label{
  float:left;
  margin: 5px;
}