2

I have an application using Chart JS and the great extension chartjs-plugin-crosshair to provide zoom and a vertical line on hover. It's ability to 'link' charts is critical as it highlights values on separate charts across the same x-axis.

The issue is the linked charts also have linked legends. I've created a simple example: https://codepen.io/sheixt/pen/JjGvbVJ

Here is an extract of the Chart option config (see the link for the full script):

const options = {
  plugins: {
    crosshair: {
      sync: {
        enabled: true
      }
    }
  },
  tooltips: {
    mode: "interpolate",
    intersect: false,
    callbacks: {
      title: function (a, d) {
        return a[0].xLabel.toFixed(2);
      },
      label: function (i, d) {
        return d.datasets[i.datasetIndex].label + ": " + i.yLabel.toFixed(2);
      }
    }
  }
};

As you can see, if you "turn off" a dataset (e.g. Dataset 1, A in chart 1, D in chart 2, and G in chart 3), the dataset is removed from all of the linked charts.

I have a series of charts that are based on the same x-axis data so the crosshair line & the tooltip appearing on all of the linked charts is ideal. But as each dataset that is plotted is not the same across the various charts, I do not want it to disappear on click.

So in my example deselecting Dataset 1 on chart 1 A would be removed but D in chart 2, and G in chart 3 should remain.

Is this feasible?

Sheixt
  • 2,546
  • 12
  • 36
  • 65

1 Answers1

0

You can extend the chart and write your own type with horizontal and vertical arbitrary lines as it is shown in this answer.

Here is an update if you need it for version 2

HTML

<canvas id="chart" width="600" height="400"></canvas>

SCRIPT

var ctx = document.getElementById('chart').getContext('2d');

Chart.defaults.crosshair = Chart.defaults.line;
Chart.controllers.crosshair = Chart.controllers.line.extend({
    draw: function (params) {
        Chart.controllers.line.prototype.draw.call(this, params);
        
        if (this.chart.tooltip._active && this.chart.tooltip._active.length) {
                var activePoint = this.chart.tooltip._active[0],
                 ctx = this.chart.ctx,
                 x = activePoint.tooltipPosition().x,
                 y = activePoint.tooltipPosition().y,
                 topY    = this.chart.scales['y-axis-0'].top,
                 bottomY = this.chart.scales['y-axis-0'].bottom,
                 startX  = this.chart.scales['x-axis-0'].left,
                 endX    = this.chart.scales['x-axis-0'].right;

               // draw line
                ctx.save();
                ctx.beginPath();
                ctx.moveTo(x, topY);
                ctx.lineTo(x, bottomY);
                ctx.moveTo(startX, y);
                ctx.lineTo(endX, y);
                ctx.lineWidth = 2.5;
                ctx.strokeStyle = 'rgb(55, 55, 55)';
                ctx.stroke();
                ctx.restore();
            }
    }
});

var chart = new Chart(ctx, {
    // The type of chart we want to create
    type: 'crosshair',

    // The data for our dataset
    data: {
        labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
        datasets: [{
            label: 'My First dataset',
            backgroundColor: 'rgba(255, 255, 255,0)',
            borderColor: 'rgb(255, 99, 132)',
            data: [0, 10, 5, 2, 20, 30, 45]
        }]
    },

    // Configuration options go here
    options: {}
});

Result enter image description here

var ctx = document.getElementById('chart').getContext('2d');

Chart.defaults.crosshair = Chart.defaults.line;
Chart.controllers.crosshair = Chart.controllers.line.extend({
    draw: function (params) {
        Chart.controllers.line.prototype.draw.call(this, params);
        
        if (this.chart.tooltip._active && this.chart.tooltip._active.length) {
                var activePoint = this.chart.tooltip._active[0],
                 ctx = this.chart.ctx,
                 x = activePoint.tooltipPosition().x,
                 y = activePoint.tooltipPosition().y,
                 topY    = this.chart.scales['y-axis-0'].top,
                 bottomY = this.chart.scales['y-axis-0'].bottom,
                 startX  = this.chart.scales['x-axis-0'].left,
                 endX    = this.chart.scales['x-axis-0'].right;

               // draw line
                ctx.save();
                ctx.beginPath();
                ctx.moveTo(x, topY);
                ctx.lineTo(x, bottomY);
                ctx.moveTo(startX, y);
                ctx.lineTo(endX, y);
                ctx.lineWidth = 2.5;
                ctx.strokeStyle = 'rgb(55, 55, 55)';
                ctx.stroke();
                ctx.restore();
            }
    }
});

var chart = new Chart(ctx, {
    // The type of chart we want to create
    type: 'crosshair',

    // The data for our dataset
    data: {
        labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
        datasets: [{
            label: 'My First dataset',
            backgroundColor: 'rgba(255, 255, 255,0)',
            borderColor: 'rgb(255, 99, 132)',
            data: [0, 10, 5, 2, 20, 30, 45]
        }]
    },

    // Configuration options go here
    options: {}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script>

<canvas id="chart" width="600" height="400"></canvas>
Virtual Device
  • 1,650
  • 3
  • 10
  • 26