4

I would like to fix y-axis position when scrolling horizontally.

Here's an example that works but without using Angular

$(document).ready(function () {

    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;
    }

    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);
        }
    }

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



    $(function () {
        var rectangleSet = false;

        var canvasTest = $('#chart-Test');
        var chartTest = new Chart(canvasTest, {
            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 () {
                        if (!rectangleSet) {
                            var sourceCanvas = chartTest.chart.canvas;
                            var copyWidth = chartTest.scales['y-axis-0'].width;
                            var copyHeight = chartTest.scales['y-axis-0'].height + chartTest.scales['y-axis-0'].top + 10;
                            var targetCtx = document.getElementById("axis-Test").getContext("2d");
                            targetCtx.canvas.width = copyWidth;
                            targetCtx.drawImage(sourceCanvas, 0, 0, copyWidth, copyHeight, 0, 0, copyWidth, copyHeight);

                            var sourceCtx = sourceCanvas.getContext('2d');
                            sourceCtx.clearRect(0, 0, copyWidth, copyHeight);
                            rectangleSet = true;
                        }
                    },
                    onProgress: function () {
                        if (rectangleSet === true) {
                            var copyWidth = chartTest.scales['y-axis-0'].width;
                            var copyHeight = chartTest.scales['y-axis-0'].height + chartTest.scales['y-axis-0'].top + 10;

                            var sourceCtx = chartTest.chart.canvas.getContext('2d');
                            sourceCtx.clearRect(0, 0, copyWidth, copyHeight);
                        }
                    }
                }
            }
        });
        addData(5, chartTest);
    });
});
.chartWrapper {
  position: relative;
}

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

.chartAreaWrapper {
  width: 600px;
  overflow-x: scroll;
}
<script src="https://github.com/chartjs/Chart.js/releases/download/v2.6.0/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="chartWrapper">
  <div class="chartAreaWrapper">
  <div class="chartAreaWrapper2">
      <canvas id="chart-Test" height="300" width="1200"></canvas>
  </div>
  </div>
  <canvas id="axis-Test" height="300" width="0"></canvas>
</div>

When I use this in my angular example , it does not work anymore, the axis does not follow the scroll

Here's a stackblitz reproduction

infodev
  • 4,673
  • 17
  • 65
  • 138

1 Answers1

3

In your StackBlitz, the section (rectanlge) of the y-axis is correctly created on the target canvas and removed from the source canvas. The problem is that the wrong div is horizontally scrolled. This can be fixed by changing the template and corresponding css.

Please have a look at the following StackBlitz.

UPDATE (dynamic data)

In cases where the chart component receives dynamically changing data through an @Input() property, your component needs to implement the OnChange lifecycle hook.

See the following StackBlitz.

Please note that this code is far from being optimized. Instead of creating the chart from scratch on every data change, you should simply update the data and options on the existing chart.

uminder
  • 23,831
  • 5
  • 37
  • 72
  • that's working, but In my real example I'm updating graph inside `ngOnChange` lifehook via `@Input()` in this case the virtual y-Axis is keeping the last values, I would it to get updated. any Idea ? – infodev Dec 06 '19 at 17:31
  • @infodef: I updated my answer with a solution for dynamically changing data provided through tn `@Input()` property. – uminder Dec 07 '19 at 15:26
  • Thanks , I get a new problem with this solution.. Its working when brower scale is 100% but if I use 75% the `clearRect` does not cover all the source axis ( You can try it on your example) – infodev Dec 09 '19 at 13:29
  • 1
    @infodev: I did a small change on my StackBlitz, please check if this works for you. – uminder Dec 09 '19 at 13:57