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
Vous êtes plutôt sur la bonne voie. Si vous ajoutez un autre wrapper et l’axe y, vous avez terminé.
Aperçu
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/
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);
}
}
}
}
});
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>
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);