Как создать горизонтальную прокрутку диаграммы Chart.js с заблокированной осью y?
Я хотел бы создать линейную диаграмму с Chart.Js
, но при перемещении Y-Axis
не перемещаться.
Я предполагаю, что могу использовать фиксированную ширину и помещать ее в контейнер div с overflow:auto
, но тогда информация Y-Axis
прикрепляется к холсту и прокручивается вперед.
Я не вижу параметр или параметр для этого в документах. Любые идеи?
Спасибо
Ответы
Ответ 1
Прокручиваемая диаграмма
Ты в значительной степени на правильном пути. Если вы добавили еще одну оболочку и ось y, вы сделали.
Предварительный просмотр
![введите описание изображения здесь]()
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/
Ответ 2
Chart.js 2.7.2: https://jsfiddle.net/EmmaLouise/eb1aqpx8/3/
Этот подход обрабатывает различные настройки DPR и масштабирует ось в соответствии с масштабом, который Chart.js применяет к своим диаграммам. Он также вызывает .clearRect() для исходной оси Y, которую рисует Chart.js, очищая пиксели в определенной области, что означает отсутствие дублирования осей или перекрытий.
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);
}
}
}
}
});
Ответ 3
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: игнорировать угловой ngFor
<div *ngFor="let graph of graphs; let i = index" class="graph">
<div class="graph-container">
<canvas #graphCanvas></canvas>
</div>
</div>
JS
Установите эти параметры:
options: {
responsive: true,
maintainAspectRatio: false
}
Установите ширину "графа-контейнера"
Я устанавливаю ширину в зависимости от количества элементов, которые у меня есть, а X - масштаб, который выбирает пользователь.
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);
Ответ 4
с последней версией (2.4.0) это сработало для меня:
HTML
<div style="width: 100%; overflow-x: auto;overflow-y:hidden">
<div style="width: 3000px, height: 300px">
<canvas id="chart1" height="300" width="0"></canvas>
</div>
</div>
Вы также можете рассчитать width
динамически на основе длины данных. Например, в VueJS вы можете сделать это следующим образом (с учетом 30px
для каждой записи):
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>
Ответ 5
<ion-content >
<div scrollX="true" scrollY="true" style="overflow:scroll; position:fixed; display:inline; top:0; right:0; bottom:0; left:0; white-space: nowrap;">
<canvas baseChart
[data]="barChartData"
[labels]="barChartLabels"
[options]="barChartOptions"
[colors]="lineChartColors"
[legend]="barChartLegend"
[chartType]="barChartType"
(chartHover)="chartHovered($event)"
(chartClick)="chartClicked($event)">
</canvas>
</div>
<button (click)="randomize()">Update</button>
</ion-content>
Это работает для меня, когда я устанавливаю холст шириной 700 пикселей и прокрутка работает плавно.
Ответ 6
Все эти ответы довольно грязные и сложные. Вот что я сделал для своего проекта. Я просто вызываю fitChart() всякий раз, когда изменяется набор данных или размер контейнера.
HTML:
<div class="chartWrapper">
<div class="chartContainer">
<canvas id="chart"></canvas>
</div>
</div>
CSS: (установите ширину и высоту на то, что вы хотите)
div.chartWrapper {
position: relative;
overflow: auto;
width: 100%;
}
div.chartContainer {
position: relative;
height: 300px;
}
JS:
var xAxisLabelMinWidth = 15; // Replace this with whatever value you like
var myChart = new Chart(document.getElementById('chart').getContext('2d'), {
type: 'line',
data: {},
options: {
responsive: true,
maintainAspectRatio: false
}
});
function fitChart(){
var chartCanvas = document.getElementById('chart');
var maxWidth = chartCanvas.parentElement.parentElement.clientWidth;
var width = Math.max(mayChart.data.labels.length * xAxisLabelMinWidth, maxWidth);
chartCanvas.parentElement.style.width = width +'px';
}