web-dev-qa-db-fra.com

Comment créer un graphique en courbes à défilement horizontal Chart.js avec un axe y verrouillé?

J'aimerais créer un graphique en courbes avec Chart.Js mais que le Y-Axis ne bouge pas lorsque je fais défiler.

Je suppose que je peux utiliser une largeur fixe et la placer dans un conteneur div avec overflow:auto, mais ensuite les informations Y-axis sont attachées au canevas et défilent. 

Je ne vois pas de paramètre ni d'option pour cela dans la documentation. Des idées?

Je vous remercie

15
Joshua Richards

Tableau défilable

Vous êtes plutôt sur la bonne voie. Si vous ajoutez un autre wrapper et l’axe y, vous avez terminé.


Aperçu

 enter image description here


CSS

.chartWrapper {
    position: relative;
}

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

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

HTML

<div class="chartWrapper">
    <div class="chartAreaWrapper">
        <canvas id="myChart" height="300" width="1200"></canvas>
    </div>
    <canvas id="myChartAxis" height="300" width="0"></canvas>
</div>

Script

...

new Chart(ctx).Line(data, {
    onAnimationComplete: function () {
        var sourceCanvas = this.chart.ctx.canvas;
        // the -5 is so that we don't copy the edges of the line
        var copyWidth = this.scale.xScalePaddingLeft - 5;
        // the +5 is so that the bottommost y axis label is not clipped off
        // we could factor this in using measureText if we wanted to be generic
        var copyHeight = this.scale.endPoint + 5;
        var targetCtx = document.getElementById("myChartAxis").getContext("2d");
        targetCtx.canvas.width = copyWidth;
        targetCtx.drawImage(sourceCanvas, 0, 0, copyWidth, copyHeight, 0, 0, copyWidth, copyHeight);
    }
});

Fiddle - http://jsfiddle.net/mbhavfwm/

23
potatopeelings

Chart.js 2.7.2: https://jsfiddle.net/EmmaLouise/eb1aqpx8/3/

Cette approche gère différents paramètres DPR et redimensionne l’axe en fonction de la normalisation appliquée par Chart.js à ses graphiques. Il appelle également .clearRect () sur l’axe Y d'origine dessiné par Chart.js, en effaçant les pixels de la zone définie, ce qui signifie qu’il n’ya pas de duplication des axes ni de chevauchement.

CSS:

.chartWrapper {
 position: relative;
}

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

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

HTML

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

JS:

    $(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 scale = window.devicePixelRatio;                       

                        var sourceCanvas = chartTest.chart.canvas;
                        var copyWidth = chartTest.scales['y-axis-0'].width - 10;
                        var copyHeight = chartTest.scales['y-axis-0'].height + chartTest.scales['y-axis-0'].top + 10;

                        var targetCtx = document.getElementById("axis-Test").getContext("2d");

                        targetCtx.scale(scale, scale);
                        targetCtx.canvas.width = copyWidth * scale;
                        targetCtx.canvas.height = copyHeight * scale;

                        targetCtx.canvas.style.width = `${copyWidth}px`;
                        targetCtx.canvas.style.height = `${copyHeight}px`;
                        targetCtx.drawImage(sourceCanvas, 0, 0, copyWidth * scale, copyHeight * scale, 0, 0, copyWidth * scale, copyHeight * scale);

                        var sourceCtx = sourceCanvas.getContext('2d');

                        // Normalize coordinate system to use css pixels.

                        sourceCtx.clearRect(0, 0, copyWidth * scale, copyHeight * scale);
                        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);
                    }
                }
            }
        }
    });
5
Emma Louise

avec la dernière version (2.4.0) cela a fonctionné pour moi:

HTML

<div style="width: 100%; overflow-x: auto;">
  <div style="width: 3000px, height: 300px">
    <canvas id="chart1" height="300" width="0"></canvas>
  </div>
</div>

Vous pouvez également calculer la valeur width de manière dynamique en fonction de la longueur des données. Par exemple, dans VueJS, vous pouvez le faire comme suit (en considérant 30px pour chaque entrée):

VueJS

<div style="width: 100%; overflow-x: auto;">
  <div :style="{width: (this.data.length * 30) + 'px', height: '300px'}">
    <canvas id="chart1" height="300" width="0"></canvas>
  </div>
</div>
0
Majid

Chart.js 2.x:

CSS:

    .graph {
        padding: 10px;
        position: relative;
        overflow-x: scroll;
        width: 100%;
        .graph-container {
            height: 500px;
            width: 100%;
            min-width: 100%
        }
    }

HTML: Ignorer le ngFor angulaire

  <div *ngFor="let graph of graphs; let i = index" class="graph">
        <div class="graph-container">
            <canvas #graphCanvas></canvas>
        </div>
  </div>

JS

Définissez ces options:

        options: {
            responsive: true,
            maintainAspectRatio: false
        }

Définir la largeur du "graph-container"

Je règle la largeur en fonction du nombre d'éléments que j'ai X un zoom que l'utilisateur choisit

graphCanvasElement.nativeElement.parentElement
    .setAttribute('style', `width: ${chartData.data.labels.length*graph.zoom}px;min-width: 100%`);

graph.chartObj = new Chart(graphCanvasElement.nativeElement.getContext('2d'), chartData);
0
Sumama Waheed