5
votes

I have following example data for a line chart:

[
 {
   x: 'Mon Sep 29 2018 14:26:53 GMT+0100',
   y: 100
 },
 {
   x: 'Mon Oct 15 2018 10:40:31 GMT+0100',
   y: 400
 }
]

My goal is to set a certain time frame as default and change it's range and zoom dynamically. If there is no data to show, it's fine.

I'm using the chartjs-plugin-zoom which allows me to pan freely on the x axis which is very good. Unfotunately the zoom is set on user events via this plugin.

Basically I want to have buttons to switch between time scalings and then pan on the x axis.

My question is, do I need to set the "limits" in ChartJS itself and let the plugin only pan? If yes, how to do this "freely" not considering the data (ChartJS tries to fit all data in the view, correct me if I'm wrong)

I tried the zoom options on the plugin, but they do not seem to affect anything:

zoom: {
        enabled: true,
        drag: false,
        mode: '',
        rangeMin: {
            x: moment().format(),
            y: null
        },
        rangeMax: {
            x: moment().add(7, 'day').format(),
            y: null
        }
    }

Thank you!

2
Hey, Did you find an answer to your question?Kshitij

2 Answers

4
votes

You have to give same data type you used in your scale.

For example:

if you are using Date object for one of the axes which you want to pan or zoom this may be helpful for you:

  import { Chart } from 'chart.js';
  import  'chartjs-plugin-zoom';

  ...


  let date_list=["2019-08-09","2019-08-10","2019-08-11","2019-08-12","2019-08-13","2019-08-14"]
  let value_list=[1000,2000,3000,2500,3000,5000]
  let start_date = new Date(date_list[0]);
  let end_date = new Date(date_list[date_list.length-1]);

  let range_min = new Date(date_list[0]);  //start date
  range_min.setDate(range_min.getDate()-10);

  let range_max = new Date(date_list[date_list.length-1]);  //end date
  range_max.setDate(range_max.getDate()+10);

  this.chart = new Chart(this.my_chart.nativeElement, {
    type: 'bar',
    data: {

      labels: date_list,
      datasets: [
        {
          data: value_list, 
        }
      ]
    },
    options: {
      responsive: true,
      scales:{
        yAxes: [{
          type: 'linear',
          ticks: {
            beginAtZero: true,
          }
        },
        ],
        xAxes: [{
          distribution: 'linear',
          type: "time",
          time: {
            min: start_date.toDateString(),
            max: end_date.toDateString(),
            unit: "day",
            stepSize: "1",
          },

        }],
      },
      pan: {
        enabled: true,
        mode: 'x',
        rangeMin: {
          x: range_min,
        },
        rangeMax: {
          x: range_max,
        },     
      },
      zoom: {
        enabled: true,         
        mode: 'x',
        threshold: 10,
        rangeMin: {
          x: range_min,
        },
        rangeMax: {
          x: range_max,
        },     
      },
    }
  });

Also don't forget to install dependencies.

0
votes

Try this

  1. Set pan enabled to false, set zoom enabled and drag to true.
  2. Set scales.xAxes[0].type to 'time'.
  3. Set scales.xAxes[0].time.min and max to first and end of data label array to limit the time scaling.
  4. Also, set pan range min and max to first and end of data label array. This will limit the pan movement.

For example:

// if your data

myChart.data.labels = [
    moment(data[0].timestamp),
    moment(data[1].timestamp),
    moment(data[2].timestamp),
    moment(data[3].timestamp)
]

// then set

pan: {
    enabled: false,
    mode: "x",
    speed: 10,
    threshold: 10,
    rangeMin: {
        x: new Date(data[0].timestamp).getTime() - offset
    },
    rangeMax: {
        x: new Date(data[3].timestamp).getTime() + offset
    }
},
zoom: {
    enabled: true,
    drag: true,
    mode: "x",
    sensitivity: 0.3,
    rangeMin: {
        x: 3600000 - offset // let say the zoom range min is 1 hour
    },
    rangeMax: {
        x: ((new Date(data[3].timestamp).getTime()) - (new Date(data[0].timestamp).getTime())) + offset
    }
},
scales: {
    xAxes: [{
        type: "time",
        time: {
            min: new Date(data[0].timestamp).getTime(),
            max: new Date(data[3].timestamp).getTime()
        }      
    }]
}

  • note: in my case timestamp is in ISO string. And labels must be in moment format.
  • note: you can also add an offset in min and max. set offset to 0 if not used.

    1. lastly to switch between pan and zoom, you need to do this:
// since myChart.update() is not working. You need to do this.

var myChartOptions = myChart.options; // need to store in variable.

if (Pan) {
    myChartOptions.pan.enabled = true;
    myChartOptions.zoom.enabled = false;
    myChartOptions.zoom.drag = false;
    myChart.options = myChartOptions; // update myChart.options.
}
else if (Zoom) {
    myChartOptions.pan.enabled = false;
    myChartOptions.zoom.enabled = true;
    myChartOptions.zoom.drag = true;
    myChart.options = myChartOptions; // update myChart.options.
}