如何实现在 Chart.js 图表上自适应缩放的滚动条?

问题描述 投票:0回答:1

我正在尝试在使用 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();
});

这是我想要实现的目标的示例。

所以我想知道是否有人成功实现了这样的滚动条,如果是的话,你是如何进行的?

charts chart.js scrollbar
1个回答
0
投票

我完全忘记了这个问题...

最后,我成功地使用自定义内联插件实现了滚动条。

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>

© www.soinside.com 2019 - 2024. All rights reserved.