Как и в заголовке, я хотел бы использовать один холст, чтобы поделиться с помощью chart.js.Я видел рядом с DOM , но это что-то еще, мне нужно сохранить один холст и сохранить анимацию.
Я использую версию Chart.js: 2.8.0 (последняя версия)Идея ретранслировать сюжет через регистрацию плагина.Первая часть работает как шарм, в beforeLayout
chart.width = chart.canvas.width * 0.6;
масштабируется первый график, работает отлично, даже всплывающие подсказки отображаются только в пределах области первых графиков.Со вторым графиком, если я установлю:
chart.width = chart.canvas.width * 0.4;
chart.options.layout.padding.left = chart.canvas.width * 0.6;
Сюжет запутывается, стеки 
ясно, что я могу установить
chart.width = chart.canvas.width * 1;
ипотом перерисовать первый график, но, может быть, есть какой-то простой способ сохранить два (или более) графиков, разделяющих холст?
Код, взятый из sample.js samples и измененный мной для обеспечения минимальной рабочей нагрузкипример.
<!DOCTYPE html>
<html><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Line Chart</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.bundle.min.js"></script>
</head>
<body>
<canvas id="canvas" width="1013" height="506" class="chartjs-render-monitor"></canvas>
<br>
<button id="randomizeData">Randomize Data</button>
<script>
var config = {
type: 'bar',
data: {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
datasets: [{
label: 'My First dataset',
backgroundColor: 'green',
borderColor: 'blue',
data: [
Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random()
],
fill: false,
}, {
label: 'My Second dataset',
fill: false,
backgroundColor: 'blue',
borderColor: 'blue',
data: [
Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random()
],
}]
},
plugins: [{
beforeLayout: function (chart) {
chart.width = chart.canvas.width * 0.6;
chart.options.layout.padding.left = 0;
},
}],
options: {
responsive: true,
title: {
display: true,
text: 'Chart.js Line Chart'
},
tooltips: {
mode: 'index',
intersect: false,
},
hover: {
mode: 'nearest',
intersect: true
},
scales: {
xAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Month'
}
}],
yAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Value'
}
}]
}
}
};
var config2 = {
type: 'bar',
data: {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
datasets: [{
label: 'My First dataset',
backgroundColor: 'green',
borderColor: 'blue',
data: [
Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random()
],
fill: false,
}, {
label: 'My Second dataset',
fill: false,
backgroundColor: 'blue',
borderColor: 'blue',
data: [
Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random()
],
}]
},
plugins: [{
beforeLayout: function (chart) {
chart.width = chart.canvas.width * 0.4;
chart.options.layout.padding.left = chart.canvas.width * 0.6;
},
}],
options: {
responsive: true,
title: {
display: true,
text: 'Chart.js Line Chart'
},
tooltips: {
mode: 'index',
intersect: false,
},
hover: {
mode: 'nearest',
intersect: true
},
scales: {
xAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Month'
}
}],
yAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Value'
}
}]
}
}
};
window.onload = function() {
var ctx = document.getElementById('canvas').getContext('2d');
window.myLine = new Chart(ctx, config);
window.myLine2 = new Chart(ctx, config2);
};
document.getElementById('randomizeData').addEventListener('click', function() {
config.data.datasets.forEach(function(dataset) {
dataset.data = dataset.data.map(function() {
return Math.random();
});
});
config2.data.datasets.forEach(function(dataset) {
dataset.data = dataset.data.map(function() {
return Math.random();
});
});
window.myLine.update();
window.myLine2.update();
});
</script>
</body></html>
Вот как выглядит желаемый результат:
Такие вещи, как отсутствующая ось Y, легенда и заголовок, скрываются простым display: false
, а верхняя часть отступа для второго графика установлена на первый график chartArea.top, проблема здесь заключается в мерцании и слишком частом перерисовке первого графика, он также получает события наведения, поэтому установка только одного отступа не нужна, поэтому для второго графика должен быть смещенустановить как-то.
Теперь я приложил усилия к тому, чтобы немного измениться и решил самостоятельно очистить, осталась глючная подсказка, всплывающая в обоих графиках и вертикальное смещение между барами обоих графиков.Также требуется перерисовка вручную при изменении размера.
<!DOCTYPE html>
<html><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Line Chart</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.bundle.min.js"></script>
</head>
<body>
<div>
<canvas id="canvas" width="1013" height="506" class="chartjs-render-monitor"></canvas>
</div>
<br>
<button id="randomizeData">Randomize Data</button>
<script>
var config = {
type: 'horizontalBar',
data: {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul'],
datasets: [{
label: 'My First dataset',
backgroundColor: 'green',
borderColor: 'blue',
data: [
Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random()
]
}, {
backgroundColor: 'blue',
borderColor: 'blue',
data: [
Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random()
],
}]
},
plugins: [{
beforeLayout: function (chart) {
chart.width = chart.canvas.width * 0.55;
chart.options.layout.padding.left = 0;
},
}],
onResize: function() {
console.log(3)
},
options: {
responsive: true,
legend: {
display: false
},
title: {
display: true,
text: 'Chart.js Test double plot'
},
tooltips: {
mode: 'index',
intersect: false,
},
hover: {
mode: 'label',
intersect: true
},
scales: {
xAxes: [{
display: false,
scaleLabel: {
display: true,
labelString: 'Month'
}
}],
yAxes: [{
display: true,
gridLines: {
display:false
}
}]
}
}
};
var config2 = {
type: 'horizontalBar',
data: {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
datasets: [{
backgroundColor: 'green',
borderColor: 'blue',
data: [
Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random()
],
fill: false,
}, {
backgroundColor: 'blue',
borderColor: 'blue',
data: [
Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random()
],
}]
},
plugins: [{
beforeLayout: function (chart) {
chart.options.layout.padding.left = chart.canvas.width * 0.55;
chart.options.layout.padding.top = myLine.chartArea.top;
},
afterDraw: function (chart) {
myLine.update();
},
}],
options: {
responsive: true,
title: {
display: false,
},
legend: {
display: false
},
tooltips: {
mode: 'index',
intersect: false,
},
hover: {
mode: 'label',
intersect: true
},
scales: {
xAxes: [{
gridLines: {
display:false
},
display: false,
scaleLabel: {
display: true,
}
}],
yAxes: [{
display: false,
}]
}
}
};
window.onload = function() {
var ctx = document.getElementById('canvas').getContext('2d');
window.myLine = new Chart(ctx, config);
myLine.clear = function() {
var canvas = this.ctx;
canvas.clearRect(0, 0, this.chartArea.right, this.height); return this.canvas;}
window.myLine2 = new Chart(ctx, config2);
myLine2.clear = function() {
var canvas = this.ctx;
canvas.clearRect(this.chartArea.left, 0, this.chartArea.right - this.chartArea.left + 15, this.height); return this.canvas;}
};
document.getElementById('randomizeData').addEventListener('click', function() {
config.data.datasets.forEach(function(dataset) {
dataset.data = dataset.data.map(function() {
return Math.random();
});
});
config2.data.datasets.forEach(function(dataset) {
dataset.data = dataset.data.map(function() {
return Math.random();
});
});
window.myLine.update();
window.myLine2.update();
});
</script>
</body></html>
Было бы даже при запуске многих обновлений, но всплывающих подсказок не было, во время анимации присутствуют два одновременно.Этот результат выглядит почти как окончательный вариант, поэтому, если кто-то задается вопросом, почему, это четыре переменные для одних и тех же данных, две связанные.Так как остались только полосы и всплывающие подсказки, я бы нарисовал несколько прямоугольников сам, если бы не анимация и тот же каркас, используемый для других графиков.Конвейер для дальнейшей обработки требует одного изображения, так что взлом холста по требованию для отрисовки их обоих невозможен.
Проблема в том, что отступы или поля игнорируются Chart.js при перерисовке.
