Skip to content

Chart.js Advanced Features

After learning Chart.js basic usage and style customization, let's explore some more advanced features. These features can help you create more complex and interactive charts.

Dataset Configuration

Chart.js provides rich dataset configuration options, allowing you to more precisely control display of each data series.

Dataset Properties

javascript
const config = {
  type: 'line',
  data: {
    labels: ['January', 'February', 'March', 'April', 'May'],
    datasets: [{
      label: 'Sales Data',
      data: [10, 20, 30, 40, 50],
      // Dataset-specific configuration
      borderColor: 'rgb(75, 192, 192)',
      backgroundColor: 'rgba(75, 192, 192, 0.2)',
      borderWidth: 2,
      pointRadius: 4,
      pointBackgroundColor: 'rgb(75, 192, 192)',
      pointBorderColor: '#fff',
      pointBorderWidth: 1,
      // Control whether to show data points
      showLine: true,
      // Control whether to fill area under curve
      fill: false,
      // Control line tension (0 is straight line, 1 is curve)
      tension: 0.1
    }]
  }
};

Multiple Datasets

You can display multiple datasets in one chart:

javascript
const config = {
  type: 'line',
  data: {
    labels: ['January', 'February', 'March', 'April', 'May'],
    datasets: [
      {
        label: 'Product A',
        data: [10, 20, 30, 40, 50],
        borderColor: 'rgb(75, 192, 192)',
        backgroundColor: 'rgba(75, 192, 192, 0.2)'
      },
      {
        label: 'Product B',
        data: [15, 25, 35, 45, 55],
        borderColor: 'rgb(255, 99, 132)',
        backgroundColor: 'rgba(255, 99, 132, 0.2)'
      }
    ]
  }
};

Interactive Features

Chart.js provides rich interactive features to enhance user experience.

Tooltip Configuration

javascript
const config = {
  type: 'bar',
  data: {
    labels: ['January', 'February', 'March', 'April', 'May'],
    datasets: [{
      label: 'Sales Data',
      data: [10, 20, 30, 40, 50],
      backgroundColor: 'rgba(75, 192, 192, 0.2)',
      borderColor: 'rgb(75, 192, 192)',
      borderWidth: 1
    }]
  },
  options: {
    plugins: {
      tooltip: {
        // Enable tooltip
        enabled: true,
        // Tooltip position
        position: 'average',
        // Custom tooltip content
        callbacks: {
          title: function(context) {
            return 'Month: ' + context[0].label;
          },
          label: function(context) {
            return context.dataset.label + ': ' + context.parsed.y + ' units';
          }
        },
        // Tooltip style
        backgroundColor: 'rgba(0, 0, 0, 0.8)',
        titleColor: '#fff',
        bodyColor: '#fff',
        borderColor: 'rgba(0, 0, 0, 0.1)',
        borderWidth: 1
      }
    }
  }
};

Legend Configuration

javascript
const config = {
  type: 'line',
  data: {
    labels: ['January', 'February', 'March', 'April', 'May'],
    datasets: [
      {
        label: 'Product A',
        data: [10, 20, 30, 40, 50],
        borderColor: 'rgb(75, 192, 192)'
      },
      {
        label: 'Product B',
        data: [15, 25, 35, 45, 55],
        borderColor: 'rgb(255, 99, 132)'
      }
    ]
  },
  options: {
    plugins: {
      legend: {
        // Display legend
        display: true,
        // Legend position
        position: 'top',
        // Legend alignment
        align: 'center',
        // Legend label configuration
        labels: {
          color: '#333',
          font: {
            size: 12,
            family: 'Arial'
          },
          // Behavior when clicking legend items
          usePointStyle: true
        }
      }
    }
  }
};

Event Handling

Chart.js allows you to add event handlers to charts to respond to user interactions.

Click Event

javascript
const config = {
  type: 'bar',
  data: {
    labels: ['January', 'February', 'March', 'April', 'May'],
    datasets: [{
      label: 'Sales Data',
      data: [10, 20, 30, 40, 50],
      backgroundColor: 'rgba(75, 192, 192, 0.2)'
    }]
  },
  options: {
    onClick: function(event, elements) {
      if (elements.length > 0) {
        const element = elements[0];
        const datasetIndex = element.datasetIndex;
        const index = element.index;

        console.log('Clicked data point:');
        console.log('Dataset index:', datasetIndex);
        console.log('Data point index:', index);
        console.log('Label:', this.data.labels[index]);
        console.log('Value:', this.data.datasets[datasetIndex].data[index]);
      }
    }
  }
};

const ctx = document.getElementById('myChart').getContext('2d');
const myChart = new Chart(ctx, config);

Hover Event

javascript
const config = {
  type: 'line',
  data: {
    labels: ['January', 'February', 'March', 'April', 'May'],
    datasets: [{
      label: 'Sales Data',
      data: [10, 20, 30, 40, 50],
      borderColor: 'rgb(75, 192, 192)'
    }]
  },
  options: {
    onHover: function(event, elements) {
      // Change mouse cursor style
      event.native.target.style.cursor = elements.length > 0 ? 'pointer' : 'default';
    }
  }
};

Dynamic Chart Updates

Chart.js supports dynamic chart data updates, very useful for real-time data visualization.

Update Data

javascript
// Assume we have already created a chart instance
const ctx = document.getElementById('myChart').getContext('2d');
const myChart = new Chart(ctx, {
  type: 'line',
  data: {
    labels: ['January', 'February', 'March', 'April', 'May'],
    datasets: [{
      label: 'Sales Data',
      data: [10, 20, 30, 40, 50],
      borderColor: 'rgb(75, 192, 192)'
    }]
  }
});

// Add new data point
function addData(chart, label, data) {
  chart.data.labels.push(label);
  chart.data.datasets.forEach((dataset) => {
    dataset.data.push(data);
  });
  chart.update();
}

// Remove data point
function removeData(chart) {
  chart.data.labels.pop();
  chart.data.datasets.forEach((dataset) => {
    dataset.data.pop();
  });
  chart.update();
}

// Update existing data point
function updateData(chart, index, newData) {
  chart.data.datasets.forEach((dataset) => {
    dataset.data[index] = newData;
  });
  chart.update();
}

Real-time Data Example

javascript
// Create a real-time updating chart
const ctx = document.getElementById('realTimeChart').getContext('2d');
const realTimeChart = new Chart(ctx, {
  type: 'line',
  data: {
    labels: [],
    datasets: [{
      label: 'Real-time Data',
      data: [],
      borderColor: 'rgb(75, 192, 192)',
      backgroundColor: 'rgba(75, 192, 192, 0.2)',
      fill: true
    }]
  },
  options: {
    scales: {
      x: {
        display: true,
        title: {
          display: true,
          text: 'Time'
        }
      },
      y: {
        display: true,
        title: {
          display: true,
          text: 'Value'
        }
      }
    },
    animation: {
      duration: 0 // Generally disable animation for real-time data
    }
  }
});

// Simulate real-time data updates
setInterval(function() {
  const now = new Date();
  const timeString = now.getHours() + ':' + now.getMinutes() + ':' + now.getSeconds();
  const newValue = Math.floor(Math.random() * 100);

  // Add new data point
  realTimeChart.data.labels.push(timeString);
  realTimeChart.data.datasets[0].data.push(newValue);

  // Keep maximum 20 data points
  if (realTimeChart.data.labels.length > 20) {
    realTimeChart.data.labels.shift();
    realTimeChart.data.datasets[0].data.shift();
  }

  realTimeChart.update();
}, 1000);

Plugin System

Chart.js has a powerful plugin system, allowing you to extend chart functionality.

Create Custom Plugin

javascript
// Create a simple plugin to display text on chart
const textPlugin = {
  id: 'textPlugin',
  beforeDraw: function(chart) {
    const ctx = chart.ctx;
    const width = chart.width;
    const height = chart.height;
    const text = 'Chart.js Advanced Features';

    ctx.save();
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.font = '16px Arial';
    ctx.fillStyle = '#666';
    ctx.fillText(text, width / 2, height / 2);
    ctx.restore();
  }
};

// Register plugin
Chart.register(textPlugin);

// Use plugin in chart configuration
const config = {
  type: 'bar',
  data: {
    labels: ['January', 'February', 'March', 'April', 'May'],
    datasets: [{
      label: 'Sales Data',
      data: [10, 20, 30, 40, 50],
      backgroundColor: 'rgba(75, 192, 192, 0.2)'
    }]
  },
  plugins: [textPlugin] // Use plugin
};

Custom Chart Types

You can also create custom chart types to meet specific needs.

Extend Existing Chart Type

javascript
// Extend line chart to add custom functionality
class CustomLineController extends Chart.controllers.line {
  draw() {
    // Call parent class draw method
    super.draw(arguments);

    // Add custom drawing logic
    const ctx = this.chart.ctx;
    const chartArea = this.chart.chartArea;

    // Draw a custom line on chart
    ctx.save();
    ctx.strokeStyle = 'red';
    ctx.lineWidth = 2;
    ctx.beginPath();
    ctx.moveTo(chartArea.left, chartArea.top + (chartArea.bottom - chartArea.top) / 2);
    ctx.lineTo(chartArea.right, chartArea.top + (chartArea.bottom - chartArea.top) / 2);
    ctx.stroke();
    ctx.restore();
  }
}

// Register custom controller
Chart.register(CustomLineController);

// Use custom chart type
const config = {
  type: 'customLine', // Use custom type
  data: {
    labels: ['January', 'February', 'March', 'April', 'May'],
    datasets: [{
      label: 'Sales Data',
      data: [10, 20, 30, 40, 50],
      borderColor: 'rgb(75, 192, 192)'
    }]
  }
};

Export and Import

Export Chart as Image

javascript
function exportChart(chart, filename) {
    const url = chart.toBase64Image();
    const link = document.createElement('a');
    link.download = filename;
    link.href = url;
    link.click();
}

// Export with options
function exportChartWithOptions(chart, filename, options = {}) {
    const url = chart.toBase64Image(options);
    const link = document.createElement('a');
    link.download = filename;
    link.href = url;
    link.click();
}

// Usage
exportChart(myChart, 'chart.png');
exportChartWithOptions(myChart, 'chart.jpg', { type: 'image/jpeg', quality: 0.9 });

Import Chart Configuration

javascript
// Save chart configuration
function saveChartConfig(chart) {
    const config = chart.config;
    const configJSON = JSON.stringify(config, null, 2);

    // Save to localStorage
    localStorage.setItem('chartConfig', configJSON);

    // Or download as file
    const blob = new Blob([configJSON], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.download = 'chart-config.json';
    link.href = url;
    link.click();
}

// Load chart configuration
function loadChartConfig(canvasId) {
    const configJSON = localStorage.getItem('chartConfig');
    if (configJSON) {
        const config = JSON.parse(configJSON);
        const ctx = document.getElementById(canvasId).getContext('2d');
        return new Chart(ctx, config);
    }
    return null;
}

Summary

In this chapter, we learned some advanced features of Chart.js:

  1. Dataset Configuration - Detailed configuration for each data series display
  2. Interactive Features - Tooltips, legends, and event handling
  3. Dynamic Updates - Real-time chart data updates
  4. Plugin System - Extend chart functionality
  5. Custom Chart Types - Create charts for specific needs
  6. Export and Import - Save and load chart configurations

These advanced features can help you create more complex and interactive charts, improving user experience. In next chapter, we will learn how to integrate Chart.js with popular frontend frameworks.

Content is for learning and research only.