chartjs水平条形图间距在2.7.1和2.7.1之间中断

时间:2018-08-03 18:52:48

标签: chart.js bar-chart

我使用JSFiddle用Chartjs创建了一个水平条形图。我能够对其进行调整,使它看起来非常接近最终版本,如您在此处看到的:https://jsfiddle.net/coder_jb/pLec5hqn/

但是,当我尝试在Web开发IDE中使用它时,我遇到了竖线垂直间距的问题。我花了比我更愿意承认的时间来追踪差异,并且最终归结为Chartjs版本。可以正常工作的版本使用2.7.1版本,但JSFiddle中使用2.7.2版本(https://jsfiddle.net/coder_jb/3tnrzeLq/4/)的相同代码将压缩竖线间距。因此,或者我在早期版本中编码有问题并很幸运,或者在2.7.2版本中可能损坏了某些内容。知道为什么会这样吗?

好(使用Chartjs 2.7.1):

let ctx = document.getElementById("canvas").getContext("2d");
let barChart = null;

let barData = [
  25, 20, 13, 24, 15, 26, 17, 28, 19, 30,
  11, 32, 13, 34, 15, 35, 16, 37, 18, 39
];

let barTooltips = [
  "host_1 (127.0.0.1) eth33", "host_1 (127.0.0.1) eth34",
  "host_2 (127.0.0.2) eth33", "host_2 (127.0.0.2) eth34",
  "host_3 (127.0.0.3) eth34", "host_3 (127.0.0.3) eth35",
  "host_4 (127.0.0.4) eth7", "host_4 (127.0.0.4) eth8",
  "host_5 (127.0.0.5) eth9", "host_5 (127.0.0.5) eth10",
  "host_5 (127.0.0.5) eth11", "host_5 (127.0.0.5) eth12",
  "host_5 (127.0.0.5) eth13", "host_5 (127.0.0.5) eth14",
  "host_6 (127.0.0.6) eth15", "host_7 (127.0.0.7) eth16",
  "host_8 (127.0.0.8) eth17", "host_8 (127.0.0.8) eth18",
  "host_9 (127.0.0.9) eth19", "host_9 (127.0.0.9) eth20"
];
let rcBackgroundColors = [
  '#00b0ff', '#43a047',
  '#ff8f00', '#c62828',
  '#df00f9', '#ffea00',
  '#4e342e', '#2979ff',
  '#00e676', '#ffc400',
  '#5cbae6', '#b6d957',
  '#fac364', '#8cd3ff',
  '#d998cb', '#f2d249',
  '#93b9c6', '#cc5a8',
  '#52bacc', '#dbdb46'
];
let ticYlabels = [];
let ticYlabelsHidden = [];

function updateTicYlabelsHidden(ticLabel) {
  if (ticLabel) {
    if (ticYlabelsHidden.includes(ticLabel)) {
      ticYlabelsHidden.splice(ticYlabelsHidden.indexOf(ticLabel), 1);
      //ticYlabels.push(ticLabel);
    } else {
      ticYlabelsHidden.push(ticLabel);
    }
  }
  initializeTicYlabels();
}

function initializeTicYlabels() {
  ticYlabels = [];
  for (let n = 0; n < barTooltips.length; ++n) {
    let label = barTooltips[n].split(" ");
    label.shift();
    let ticLabel = label.join(' ');
    if (!ticYlabelsHidden.includes(ticLabel))
      ticYlabels.push(ticLabel);
  }
}

initializeTicYlabels();

let barBackgroundColor = [];
let maxColors = 20;
let barDataSets = [];
for (let n = 0; n < barTooltips.length; ++n) {
  barBackgroundColor.push(rcBackgroundColors[n % maxColors]);
  barDataSets[n] = {
    label: [ticYlabels[n]],
    data: [barData[n]],
    backgroundColor: rcBackgroundColors[n % maxColors],
    borderColor: rcBackgroundColors[n % maxColors],
    borderWidth: 2,
    hoverBorderWidth: 0
  };
}

let xMax = Math.max(...barData);
xMax += xMax / 10;
let pktSrcBarChartConfig = {
  animation: false,
  responsive: true,
  maintainAspectRatio: false,
  type: 'horizontalBar',
  data: {
    datasets: barDataSets,
    labels: ticYlabels,
  },

  options: {
    barValueSpacing: 10,
    tooltips: {
      mode: 'y',
      callbacks: {
        title: function() {
          return '';
        },
        label: function(tooltipItem) {
          return barTooltips[tooltipItem.index] + ':  ' + tooltipItem.xLabel + ' KB/sec';
        }
      }
    },
    legend: false,
    legendCallback: function(chart) {
      let text = [];
      text.push('<ul class="' + chart.id + '-legend">');
      for (let i = 0; i < chart.data.datasets.length; i++) {
        text.push('<li><i class="fa fa-1x fa-check-square" style="color: ' + chart.data.datasets[i].backgroundColor + ';">');
        if (chart.data.datasets[i].label) {
          text.push('&nbsp;<span style="color: black; font-size: 16px; font-family: ubuntu monospace">' + chart.data.datasets[i].label);
        }
        text.push('</i></li>');
      }
      text.push('</ul>');
      return text.join('');
    },
    title: {
      display: true,
      text: 'Bandwidth',
      fontWeight: 'bold',
      fontFamily: 'Ubuntu',
      fontSize: 18,
    },
    scales: {
      xAxes: [{
        scaleLabel: {
          display: true,
          labelString: 'KB/sec',
          fontWeight: 'bold',
          fontFamily: 'Ubuntu',
          fontSize: 18,
        },
        ticks: {
          min: 0,
          suggestedMax: xMax,
          beginAtZero: true,
        },
        gridLines: {
          offsetGridLines: true
        }
      }],
      yAxes: [{
        //id: 'ip',
        //type: 'category',
        barPercentage: 0.8,
        categoryPercentage: 1,
        maxBarThickness: 30,
        scaleLabel: {
          display: true,
          labelString: 'Packet Source',
          fontWeight: 'bold',
          fontFamily: 'Ubuntu',
          fontSize: 18,
        },
      }]
    },
    
    plugins: {
      datalabels: {
        align: 'end',
        anchor: 'end',
        formatter: function(value, context) {
          return value;
        },
        display: function(context) {
          return context.chart.isDatasetVisible(context.datasetIndex);
        }
      }
    } 
  }
}

function legendClickCallback(event) {
  event = event || window.event;
  let target = event.target || event.srcElement;
  while (target.nodeName !== 'LI') {
    target = target.parentElement;
  }
  let parent = target.parentElement;
  let chartId = parseInt(parent.classList[0].split("-")[0], 10);
  let chart = Chart.instances[chartId];
  let index = Array.prototype.slice.call(parent.children).indexOf(target);

  if (chart.isDatasetVisible(index)) {
    target.classList.add('hiddenItem');
    target.firstChild.classList.remove('fa-check-square');
    target.firstChild.classList.add('fa-square');
    chart.data.datasets[index].hidden = true;
  } else {
    target.classList.remove('hiddenItem');
    target.firstChild.classList.remove('fa-square');
    target.firstChild.classList.add('fa-check-square');
    chart.data.datasets[index].hidden = false;
  }
  updateTicYlabelsHidden(target.innerText.trim());
  barChart.data.labels = ticYlabels;
  barChart.update();
}

barChart = new Chart(ctx, pktSrcBarChartConfig);
// Generate custom html legend with checkboxes instead of colored rectangles
let myLegendContainer = document.getElementById("legendDiv");
myLegendContainer.innerHTML = barChart.generateLegend();

// Bind onClick event to all LI-tags of the legend
let legendItems = myLegendContainer.getElementsByTagName('li');
for (let i = 0; i < legendItems.length; i += 1) {
  legendItems[i].addEventListener("click", legendClickCallback, false);
}
[class="0-legend"] {
  list-style: none;
  cursor: pointer;
  padding-left: 0;
  display: table-row;
}

[class="0-legend"] li {
  display: inline-block;
  padding: 0 5px;
}

[class="0-legend"] li.hiddenItem span {
  text-decoration: line-through;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.bundle.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<div id="legendDiv" class="noselect"></div>
<div id="container" style="width:95%;">
  <canvas id="canvas"></canvas>
</div>

不良(使用Chartjs 2.7.2):

let ctx = document.getElementById("canvas").getContext("2d");
let barChart = null;

let barData = [
  25, 20, 13, 24, 15, 26, 17, 28, 19, 30,
  11, 32, 13, 34, 15, 35, 16, 37, 18, 39
];

let barTooltips = [
  "host_1 (127.0.0.1) eth33", "host_1 (127.0.0.1) eth34",
  "host_2 (127.0.0.2) eth33", "host_2 (127.0.0.2) eth34",
  "host_3 (127.0.0.3) eth34", "host_3 (127.0.0.3) eth35",
  "host_4 (127.0.0.4) eth7", "host_4 (127.0.0.4) eth8",
  "host_5 (127.0.0.5) eth9", "host_5 (127.0.0.5) eth10",
  "host_5 (127.0.0.5) eth11", "host_5 (127.0.0.5) eth12",
  "host_5 (127.0.0.5) eth13", "host_5 (127.0.0.5) eth14",
  "host_6 (127.0.0.6) eth15", "host_7 (127.0.0.7) eth16",
  "host_8 (127.0.0.8) eth17", "host_8 (127.0.0.8) eth18",
  "host_9 (127.0.0.9) eth19", "host_9 (127.0.0.9) eth20"
];
let rcBackgroundColors = [
  '#00b0ff', '#43a047',
  '#ff8f00', '#c62828',
  '#df00f9', '#ffea00',
  '#4e342e', '#2979ff',
  '#00e676', '#ffc400',
  '#5cbae6', '#b6d957',
  '#fac364', '#8cd3ff',
  '#d998cb', '#f2d249',
  '#93b9c6', '#cc5a8',
  '#52bacc', '#dbdb46'
];
let ticYlabels = [];
let ticYlabelsHidden = [];

function updateTicYlabelsHidden(ticLabel) {
  if (ticLabel) {
    if (ticYlabelsHidden.includes(ticLabel)) {
      ticYlabelsHidden.splice(ticYlabelsHidden.indexOf(ticLabel), 1);
      //ticYlabels.push(ticLabel);
    } else {
      ticYlabelsHidden.push(ticLabel);
    }
  }
  initializeTicYlabels();
}

function initializeTicYlabels() {
  ticYlabels = [];
  for (let n = 0; n < barTooltips.length; ++n) {
    let label = barTooltips[n].split(" ");
    label.shift();
    let ticLabel = label.join(' ');
    if (!ticYlabelsHidden.includes(ticLabel))
      ticYlabels.push(ticLabel);
  }
}

initializeTicYlabels();

let barBackgroundColor = [];
let maxColors = 20;
let barDataSets = [];
for (let n = 0; n < barTooltips.length; ++n) {
  barBackgroundColor.push(rcBackgroundColors[n % maxColors]);
  barDataSets[n] = {
    label: [ticYlabels[n]],
    data: [barData[n]],
    backgroundColor: rcBackgroundColors[n % maxColors],
    borderColor: rcBackgroundColors[n % maxColors],
    borderWidth: 2,
    hoverBorderWidth: 0
  };
}

let xMax = Math.max(...barData);
xMax += xMax / 10;
let pktSrcBarChartConfig = {
  animation: false,
  responsive: true,
  maintainAspectRatio: false,
  type: 'horizontalBar',
  data: {
    datasets: barDataSets,
    labels: ticYlabels,
  },

  options: {
    barValueSpacing: 10,
    tooltips: {
      mode: 'y',
      callbacks: {
        title: function() {
          return '';
        },
        label: function(tooltipItem) {
          return barTooltips[tooltipItem.index] + ':  ' + tooltipItem.xLabel + ' KB/sec';
        }
      }
    },
    legend: false,
    legendCallback: function(chart) {
      let text = [];
      text.push('<ul class="' + chart.id + '-legend">');
      for (let i = 0; i < chart.data.datasets.length; i++) {
        text.push('<li><i class="fa fa-1x fa-check-square" style="color: ' + chart.data.datasets[i].backgroundColor + ';">');
        if (chart.data.datasets[i].label) {
          text.push('&nbsp;<span style="color: black; font-size: 16px; font-family: ubuntu monospace">' + chart.data.datasets[i].label);
        }
        text.push('</i></li>');
      }
      text.push('</ul>');
      return text.join('');
    },
    title: {
      display: true,
      text: 'Bandwidth',
      fontWeight: 'bold',
      fontFamily: 'Ubuntu',
      fontSize: 18,
    },
    scales: {
      xAxes: [{
        scaleLabel: {
          display: true,
          labelString: 'KB/sec',
          fontWeight: 'bold',
          fontFamily: 'Ubuntu',
          fontSize: 18,
        },
        ticks: {
          min: 0,
          suggestedMax: xMax,
          beginAtZero: true,
        },
        gridLines: {
          offsetGridLines: true
        }
      }],
      yAxes: [{
        //id: 'ip',
        //type: 'category',
        barPercentage: 0.8,
        categoryPercentage: 1,
        maxBarThickness: 30,
        scaleLabel: {
          display: true,
          labelString: 'Packet Source',
          fontWeight: 'bold',
          fontFamily: 'Ubuntu',
          fontSize: 18,
        },
      }]
    },
    
    plugins: {
      datalabels: {
        align: 'end',
        anchor: 'end',
        formatter: function(value, context) {
          return value;
        },
        display: function(context) {
          return context.chart.isDatasetVisible(context.datasetIndex);
        }
      }
    } 
  }
}

function legendClickCallback(event) {
  event = event || window.event;
  let target = event.target || event.srcElement;
  while (target.nodeName !== 'LI') {
    target = target.parentElement;
  }
  let parent = target.parentElement;
  let chartId = parseInt(parent.classList[0].split("-")[0], 10);
  let chart = Chart.instances[chartId];
  let index = Array.prototype.slice.call(parent.children).indexOf(target);

  if (chart.isDatasetVisible(index)) {
    target.classList.add('hiddenItem');
    target.firstChild.classList.remove('fa-check-square');
    target.firstChild.classList.add('fa-square');
    chart.data.datasets[index].hidden = true;
  } else {
    target.classList.remove('hiddenItem');
    target.firstChild.classList.remove('fa-square');
    target.firstChild.classList.add('fa-check-square');
    chart.data.datasets[index].hidden = false;
  }
  updateTicYlabelsHidden(target.innerText.trim());
  barChart.data.labels = ticYlabels;
  barChart.update();
}

barChart = new Chart(ctx, pktSrcBarChartConfig);
// Generate custom html legend with checkboxes instead of colored rectangles
let myLegendContainer = document.getElementById("legendDiv");
myLegendContainer.innerHTML = barChart.generateLegend();

// Bind onClick event to all LI-tags of the legend
let legendItems = myLegendContainer.getElementsByTagName('li');
for (let i = 0; i < legendItems.length; i += 1) {
  legendItems[i].addEventListener("click", legendClickCallback, false);
}
[class="0-legend"] {
  list-style: none;
  cursor: pointer;
  padding-left: 0;
  display: table-row;
}

[class="0-legend"] li {
  display: inline-block;
  padding: 0 5px;
}

[class="0-legend"] li.hiddenItem span {
  text-decoration: line-through;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<div id="legendDiv" class="noselect"></div>
<div id="container" style="width:95%;">
  <canvas id="canvas"></canvas>
</div>

0 个答案:

没有答案