2
votes

I'm having trouble trying to figure out the correct setup to have a ChartJS Bar Chart that has a fixed canvas height but allows the width be overflow-x. I have found an example here...http://jsfiddle.net/mbhavfwm/ which uses ChartJS 1.0, but I'm using ChartJS 2.6. So, I found another example here http://jsfiddle.net/jmpxgufu/ which uses ChartJS 2, but this example shows the chart rendered with only a few values and then ADDS more to it using javascript which then causes the width to overflow. Not quite the same.

My problem is I can not figure out how to make the chart render at the fixed height with all the data already in it, but NOT try to constrain the canvas to the width of the parent container. I want it to overflow.

Here is what I have so far. https://jsfiddle.net/fed79b7t/

HTML

<div class="chartWrapper">
  <div class="chartAreaWrapper">
    <canvas id="chart-FuelSpend" height="300" width="1200"></canvas>
  </div>
  <canvas id="axis-FuelSpend" height="300" width="0"></canvas>
</div>

CSS

.chartWrapper {
  position: relative;
}

.chartWrapper > canvas {
  position: absolute;
  left: 0;
  top: 0;
  pointer-events: none;
}

.chartAreaWrapper {
  width: 600px;
  overflow-x: scroll;
}

JAVASCRIPT

function generateLabels() {
  var chartLabels = [];
  for (x = 0; x < 100; x++) {
    chartLabels.push("Label" + x);
  }
  return chartLabels;
}

function generateData() {
  var chartData = [];
  for (x = 0; x < 100; x++) {
    chartData.push(Math.floor((Math.random() * 100) + 1));
  }
  return chartData;
}

var chartData = {
  labels: generateLabels(),
  datasets: [{
    label: "Test Data Set",
    data: generateData()
  }]
};

$(function() {
  var canvasFuelSpend = $('#chart-FuelSpend');
  var chartFuelSpend = new Chart(canvasFuelSpend, {
    type: 'bar',
    data: chartData,
    maintainAspectRatio: false,
    responsive: true,
    options: {
      tooltips: {
        titleFontSize: 0,
        titleMarginBottom: 0,
        bodyFontSize: 12
      },
      legend: {
        display: false
      },
      scales: {
        xAxes: [{
          ticks: {
            fontSize: 12,
            display: false
          }
        }],
        yAxes: [{
          ticks: {
            fontSize: 12,
            beginAtZero: true
          }
        }]
      },
      animation: {
        onComplete: function() {
          var sourceCanvas = chartFuelSpend.chart.canvas;
          var copyWidth = chartFuelSpend.scales['y-axis-0'].width - 10;
          var copyHeight = chartFuelSpend.scales['y-axis-0'].height + chartFuelSpend.scales['y-axis-0'].top + 10;
          var targetCtx = document.getElementById("axis-FuelSpend").getContext("2d");
          targetCtx.canvas.width = copyWidth;
          targetCtx.drawImage(sourceCanvas, 0, 0, copyWidth, copyHeight, 0, 0, copyWidth, copyHeight);
        }
      }
    }
  });
});

So, my goal is to have the chart the full 1200 pixels as defined by the canvas width, but for the container div to only show the 600 pixel amount where I can scroll the container to see the rest of the chart while keeping the Y-axis in place.

Can anyone shed some light on what I'm doing wrong? What am I missing?

Thank you!!!!!

1

1 Answers

1
votes

It seems to have something to do with the fact you're missing a wrapper around the canvas. Here's an updated version of your fiddle. I've added a function called addData that takes the number of new entries you want to add and the chart variable. It's not as good as it can be (because i'm not 100% sure how you want to add new data) but it's a great starting point. The trick is to not initialize the chart with all data included, you want to create the chart and then add to it later to expand the canvas, otherwise the initial render will work to fit all of the data in at that width.

https://jsfiddle.net/qmqmg82z/3/

Additional JavaScript code:

function addData(numData, chart){
    for (var i = 0; i < numData; i++){
        chart.data.datasets[0].data.push(Math.random() * 100);
        chart.data.labels.push("Label" + i);
        var newwidth = $('.chartAreaWrapper2').width() +60;
        $('.chartAreaWrapper2').width(newwidth);
    }
}

and then at the end of your page load function (or wherever you want to be adding new data) add this function call:

addData(5, chartFuelSpend);

But bear in mind this will require however much data you want to add and the chart instance.

And the HTML:

<div class="chartWrapper">
  <div class="chartAreaWrapper">
      <div class="chartAreaWrapper2">
          <canvas id="chart-FuelSpend" height="300" width="1200"></canvas>
      </div>
  </div>
  <canvas id="axis-FuelSpend" height="300" width="0"></canvas>
</div>

I'm guessing the problem was that because the width of the single wrapper you had was changing along with the chart, it meant that the horizontal scroll wasn't being applied, this way the outer wrapper has the fixed width while the inside one and the canvas can expand.