我正在尝试在使用 Chart.js 制作的图表上实现一个适应缩放的滚动条。 我发现了几篇文章可以让我实现滚动条。于是我做了一支码笔来尝试一下。
但是,我意识到问题仍然存在。 每当我放大时,滚动条都不会适应以覆盖整个图表。换句话说,放大后,我无法再滚动整个图表。 我成功地使用 FusionCharts 达到了预期的结果,但使用 Chart.js 却没有。 “问题”是我这样做的方式是 FusionCharts 固有的,并且没有代码可以从中获取灵感来使用 Chart.js 实现它。
FusionCharts.ready(function() {
var myChart = new FusionCharts({
type: "zoomline",
renderAt: "chart-container",
width: "100%",
height: "100%",
dataFormat: "json",
dataSource
}).render();
});
所以我想知道是否有人成功实现了这样的滚动条,如果是的话,你是如何进行的?
我完全忘记了这个问题...
最后,我成功地使用自定义内联插件实现了滚动条。
var canvas = document.getElementById('myCanvas'),
ctx = canvas.getContext('2d'),
isDragging,
rectPosition = null;
function generateData(number){
let data = [];
for (let i = 0; i < number ; i++){
data.push(Math.random()*10);
}
return data;
}
function generateLabels(number){
let labels = [];
for (let i = 0; i < number ; i++){
labels.push(i);
}
return labels;
}
function generateDatasets(nbrDatasets, nbrData) {
var datasets = [];
for(let i = 0 ; i < nbrDatasets ; i++ ){
datasets.push({data: generateData(nbrData), pointRadius: 0, pointHoverRadius: 7, label: `Dataset ${i}`});
}
return datasets;
}
var cfg = {
type: 'line',
data:{
labels: generateLabels(100),
datasets: generateDatasets(2, 100),
},
options:{
animations: false,
responsive: true,
maintainAspectRatio: false,
normalized: true,
layout: {
padding: {
bottom: 40,
},
},
interaction:{
mode: 'nearest',
intersect: false,
axis: 'x'
},
plugins:{
zoom:{
zoom:{
drag:{
modifierKey: 'shift',
enabled:true,
},
mode: 'x',
}
}
}
},
plugins:[{
id: "zoomRangeSlider",
afterDatasetsDraw(chart, args, plugins) {
var chartMin = chart.data.labels[0],
chartMax = chart.data.labels[chart.data.labels.length - 1],
currentZoom = chart.options.scales.x.max - chart.options.scales.x.min,
minMaxDiff = chartMax - chartMin,
posX;
const {
ctx,
chartArea: {
left,
top,
bottom,
right,
width
},
} = chart;
var rectWidth = (currentZoom / minMaxDiff) * width;
if(rectWidth < 7) {
rectWidth = 7;
}
posX = (chart.options.scales.x.min - chartMin) / minMaxDiff;
rectPosition = (posX * (width)) + (rectWidth / 2) + left;
if (rectPosition < left + rectWidth / 2) {
rectPosition = left + rectWidth / 2
}
// Scrollbar background
ctx.beginPath();
ctx.fillStyle = "#f0f0f0";
ctx.rect(left, bottom + 40, width, 15);
ctx.fill();
// Scrollbar
ctx.beginPath();
ctx.fillStyle = "#cdcdcd";
ctx.rect(rectPosition - (rectWidth / 2), bottom + 40, rectWidth, 13);
ctx.fill();
},
afterEvent(chart, args, plugins) {
var chartMin = chart.data.labels[0],
chartMax = chart.data.labels[chart.data.labels.length - 1],
currentZoom = chart.options.scales.x.max - chart.options.scales.x.min,
step = chart.data.labels[1] - chart.data.labels[0],
minMaxDiff = chartMax - chartMin;
const {
ctx,
canvas,
chartArea: {
left,
top,
bottom,
right,
width
},
} = chart;
if (args.event.type === "mousemove" && isDragging === true && args.event.y > 1.05 * bottom) {
// Check where the mouse is
var xPosition = parseFloat(((args.event.x-left) / (right-left)).toFixed(2));
xPosition = xPosition > 1 ? 1 : xPosition < 0 ? 0 : xPosition;
var min = chartMin + (xPosition * minMaxDiff) - (0.5 * currentZoom) - (chartMin + (xPosition * minMaxDiff) - (0.5 * currentZoom)) % step,
max = min + currentZoom;
if (max >= chartMax) {
max = chartMax;
min = max - currentZoom;
} else if (min < chartMin) {
min = chartMin;
max = min + currentZoom;
}
chart.options.scales.x.min = min;
chart.options.scales.x.max = max;
args.changed = true;
// Synchronize the grid and the chart
chart.update('none');
}
},
}]
};
const myChart = new Chart(ctx, cfg);
canvas.onmousedown = function(){
isDragging = true;
};
canvas.onmouseup = function(){
isDragging = false;
};
function zoomout(){
myChart.options.scales.x.min = undefined;
myChart.options.scales.x.max = undefined;
myChart.update('none');
}
.container {
height: 400px;
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.umd.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/chartjs-plugin-zoom.min.js "></script>
<div class="container">
<button onclick="zoomout()">Zoom out</button>
<canvas id='myCanvas'></canvas>
</div>