svelte-chartjs

repository·master·Indexed 43 days ago

https://github.com/sauravkanchan/svelte-chartjs

A Svelte wrapper for Chart.js version 4.0.1 that provides easy-to-use components for various chart types—including Bar, Bubble, Doughnut, Line, Pie, PolarArea, Radar, and Scatter—while maintaining full access to the underlying Chart.js instance via the bind:chart directive.

Tokens
12.7K
Snippets
35
Records
47
Agent score
53%

What's inside svelte-chartjs

  1. Optimize bundle size with Tree-shaking

    master

    Since Chart.js v3+ is tree-shakable, you can reduce your bundle size by importing and registering only the specific controllers, elements, scales, and plugins you need.

    Recommended (Tree-shakable): Manually import and register required modules.

    Lazy (Registers everything): Importing 'chart.js/auto' will register all components automatically, but it prevents tree-shaking.

    Note: Typed chart components like Line or Bar automatically register their own controllers, so you do not need to manually register LineController or BarController.

    // Tree-shakable way (recommended)
    import {
      Chart as ChartJS,
      Title, Tooltip, Legend,
      LineElement, LinearScale, PointElement, CategoryScale,
    } from 'chart.js';
    
    ChartJS.register(
      Title, Tooltip, Legend,
      LineElement, LinearScale, PointElement, CategoryScale
    );
  2. How reactivity works in svelte-chartjs

    master

    svelte-chartjs uses a Svelte $effect to watch the data, options, and updateMode props.

    When a change is detected, the library uses a freeze() helper (utilizing $state.snapshot()) to strip Svelte's deep reactivity proxies. This ensures that the raw data is passed to Chart.js. Unlike react-chartjs-2, which performs dataset merging via labels, svelte-chartjs performs a full data replacement on every update, relying on Svelte's fine-grained reactivity to manage efficiency.

  3. Handle reactive data updates in svelte-chartjs

    master

    svelte-chartjs automatically updates charts when the data or options props change. You do not need to call manual chart.update() methods. To trigger an update, use standard Svelte reactivity by reassigning your $state object.

    <script>
      import { Line } from 'svelte-chartjs';
    
      let data = $state({
        labels: ['Jan', 'Feb', 'Mar'],
        datasets: [{ label: 'Sales', data: [10, 20, 30] }],
      });
    
      function addPoint() {
        // Reassigning the data object triggers the update
        data = {
          ...data,
          labels: [...data.labels, 'Apr'],
          datasets: data.datasets.map((ds) => ({
            ...ds,
            data: [...ds.data, 40],
          })),
        };
      }
    </script>
    
    <button onclick={addPoint}>Add</button>
    <Line {data} options={{ responsive: true }} />
  4. Quick Start with svelte-chartjs

    master

    To create a chart, import the specific chart component (e.g., Line) from svelte-chartjs and the necessary Chart.js modules. You must register the Chart.js modules using ChartJS.register() before rendering the component.

    <script>
      import { Line } from 'svelte-chartjs';
      import {
        Chart as ChartJS,
        Title,
        Tooltip,
        Legend,
        LineElement,
        LinearScale,
        PointElement,
        CategoryScale,
      } from 'chart.js';
    
      ChartJS.register(
        Title, Tooltip, Legend,
        LineElement, LinearScale, PointElement, CategoryScale
      );
    
      const data = {
        labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
        datasets: [{
          label: 'Sales',
          data: [65, 59, 80, 81, 56, 55],
          borderColor: 'rgb(75, 192, 192)',
          fill: false,
        }],
      };
    </script>
    
    <Line {data} options={{ responsive: true }} />
  5. Create gradient fills using bind:chart

    master

    To apply canvas gradients to your charts, use the bind:chart directive on a Svelte component to capture the chart instance. Once the component is mounted, you can access the canvas context via chart.ctx to create a CanvasGradient (e.g., using createLinearGradient).

    Important Requirements:

    1. Lifecycle: You must create the gradient inside an onMount block (or similar lifecycle hook) to ensure chart.ctx and chart.chartArea are fully initialized.
    2. Plugins: If you are using the fill: true option to apply the gradient to the area under a line, you must register the Filler plugin from chart.js.
    3. Application: Apply the resulting gradient object to the backgroundColor property within your data object.
    <script>
      import { onMount } from 'svelte';
      import { Line } from 'svelte-chartjs';
      import {
        Chart as ChartJS,
        Title, Tooltip, Legend,
        LineElement, LinearScale, PointElement, CategoryScale, Filler,
      } from 'chart.js';
    
      // 1. Register necessary plugins (Filler is required for area fills)
      ChartJS.register(
        Title, Tooltip, Legend,
        LineElement, LinearScale, PointElement, CategoryScale, Filler
      );
    
      let chart = $state(null);
    
      let data = $state({
        labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
        datasets: [{
          label: 'Sales',
          data: [65, 59, 80, 81, 56, 55, 40],
          fill: true,
          borderColor: 'rgb(75, 192, 192)',
          backgroundColor: 'rgba(75, 192, 192, 0.2)',
          tension: 0.4,
        }],
      });
    
      onMount(() => {
        if (!chart) return;
    
        // 2. Access the context and chart area to create the gradient
        const ctx = chart.ctx;
        const gradient = ctx.createLinearGradient(0, 0, 0, chart.chartArea.bottom);
        gradient.addColorStop(0, 'rgba(75, 192, 192, 0.6)');
        gradient.addColorStop(1, 'rgba(75, 192, 192, 0.0)');
    
        // 3. Update the data with the gradient
        data = {
          ...data,
          datasets: [{ ...data.datasets[0], backgroundColor: gradient }],
        };
      });
    </script>
    
    <!-- 4. Bind the chart instance -->
    <Line bind:chart {data} options={{ responsive: true }} />
  6. Handle chart click events with svelte-chartjs

    master

    To handle user interactions like clicks on a chart, use the onclick prop on the <Chart /> component. To access meaningful data (like specific data points or datasets) from the raw event, you must use the provided utility functions: getDatasetAtEvent, getElementAtEvent, or getElementsAtEvent.

    These utilities require a reference to the chart instance, which you can obtain by using the bind:chart directive on the <Chart /> component.

    <script>
      import {
        Chart,
        getDatasetAtEvent,
        getElementAtEvent,
        getElementsAtEvent,
      } from 'svelte-chartjs';
    
      const data = { /* ... */ };
      let chart;
    
      function onClick(event) {
        if (!chart) return;
    
        // Use utilities to extract data from the event
        const dataset = getDatasetAtEvent(chart, event);
        const element = getElementAtEvent(chart, event);
        const elements = getElementsAtEvent(chart, event);
    
        if (element.length > 0) {
          const { datasetIndex, index } = element[0];
          console.log('Clicked value:', data.datasets[datasetIndex].data[index]);
        }
      }
    </script>
    
    <Chart bind:chart type="bar" onclick={onClick} {data} />
  7. Use the Pie component from svelte-chartjs

    master

    To render a Pie chart, import the Pie component from svelte-chartjs. You must also import and register the necessary Chart.js components (such as ArcElement, CategoryScale, Title, Tooltip, and Legend) using ChartJS.register() to ensure the chart renders correctly.

    Pass a data object containing labels and datasets to the component. You can also pass a options object to configure Chart.js behavior like responsiveness.

    <script>
      import { Pie } from 'svelte-chartjs';
      import {
        Chart as ChartJS,
        Title, Tooltip, Legend, ArcElement, CategoryScale,
      } from 'chart.js';
    
      ChartJS.register(Title, Tooltip, Legend, ArcElement, CategoryScale);
    
      const data = {
        labels: ['Red', 'Green', 'Yellow', 'Grey', 'Dark Grey'],
        datasets: [{
          data: [300, 50, 100, 40, 120],
          backgroundColor: ['#F7464A', '#46BFBD', '#FDB45C', '#949FB1', '#4D5360'],
        }],
      };
    </script>
    
    <Pie {data} options={{ responsive: true }} />
  8. Use the Bubble Chart component

    master

    To render a bubble chart, import the Bubble component from svelte-chartjs. You must also import and register the necessary Chart.js components (such as Title, Tooltip, Legend, PointElement, and LinearScale) using ChartJS.register to ensure the chart renders correctly.

    Pass your data object to the data prop and configuration to the options prop.

    <script>
      import { Bubble } from 'svelte-chartjs';
      import {
        Chart as ChartJS,
        Title, Tooltip, Legend, PointElement, LinearScale,
      } from 'chart.js';
    
      ChartJS.register(Title, Tooltip, Legend, PointElement, LinearScale);
    
      const data = {
        labels: 'Bubble',
        datasets: [
          {
            label: 'John',
            data: [{ x: 3, y: 7, r: 10 }],
            backgroundColor: '#ff6384',
          },
          {
            label: 'Peter',
            data: [{ x: 3.2, y: 7, r: 10 }],
            backgroundColor: '#44e4ee',
          },
        ],
      };
    </script>
    
    <Bubble {data} options={{ responsive: true }} />
  9. Use the Radar component

    master

    To render a Radar chart, import the Radar component from svelte-chartjs. You must also import and register the necessary chart.js components (such as RadialLinearScale, PointElement, and LineElement) to ensure the chart renders correctly. Pass your chart data via the data prop and configuration via the options prop.

    <script>
      import { Radar } from 'svelte-chartjs';
      import {
        Chart as ChartJS,
        Title, Tooltip, Legend,
        PointElement, RadialLinearScale, LineElement,
      } from 'chart.js';
    
      // Register required Chart.js modules
      ChartJS.register(Title, Tooltip, Legend, PointElement, RadialLinearScale, LineElement);
    
      const data = {
        labels: ['Eating', 'Drinking', 'Sleeping', 'Designing', 'Coding', 'Cycling', 'Running'],
        datasets: [
          {
            label: 'My First dataset',
            backgroundColor: 'rgba(194, 116, 161, 0.5)',
            borderColor: 'rgb(194, 116, 161)',
            data: [65, 59, 90, 81, 56, 55, 40],
          },
          {
            label: 'My Second dataset',
            backgroundColor: 'rgba(71, 225, 167, 0.5)',
            borderColor: 'rgb(71, 225, 167)',
            data: [28, 48, 40, 19, 96, 27, 100],
          },
        ],
      };
    </script>
    
    <Radar {data} options={{ responsive: true }} />