chartjs / chartjs-plugin-zoom

Zoom and pan plugin for Chart.js
MIT License
598 stars 327 forks source link

chartjs-plugin-zoom doesn't seem to work with chartjs-chart-wordcloud (React) #771

Closed BlackWolf00 closed 3 hours ago

BlackWolf00 commented 1 year ago

I implemented both packages and the dependecies, followed the guide of chartjs-plugin-zoom and tried different combinations of options but nothing happened, the zoom don't work. I'm working with React.

Packages:

"chart.js": "^4.3.0",
"chartjs-chart-wordcloud": "^4.2.0",
"chartjs-plugin-zoom": "^2.0.1",
"hammerjs": "^2.0.8",
"react": "^18.2.0",
"react-chartjs-2": "^5.2.0",

Below my simplified code:

General WordCloudComponent for reuse:

import { Chart } from 'react-chartjs-2';
import { Chart as ChartJS, ArcElement, CategoryScale, BarElement, LinearScale, Tooltip } from 'chart.js';
import { WordCloudChart, WordCloudController, WordElement } from 'chartjs-chart-wordcloud';
import zoomPlugin from 'chartjs-plugin-zoom';

function WordCloudComponent({ options, data }) {
  ChartJS.register(WordCloudChart, WordCloudController, WordElement, ArcElement, CategoryScale, BarElement, LinearScale, Tooltip, zoomPlugin);

  return (
    <div style={{ width: windowWidth, height: '600px', display: 'grid' }}>
      <div style={{ width: windowWidth, placeSelf: 'center', height: '600px' }}>
        <Chart type="wordCloud" options={options} data={data} />
      </div>
    </div>
  );
}

export default WordCloudComponent;

Component calling WordCloudComponent:

import { useState, useEffect } from 'react';
import { Button, Grid, OutlinedInput, Slider, Typography } from '@mui/material';
import WordCloudComponent from './WordCloudComponent';

function WordCloud() {

  const [option, setOption] = useState({});
  const [data, setData] = useState({});
  const [complete, setComplete] = useState(false);

  useEffect(() => {
    if (tagcloud) {
      setOption({
        plugins: {
          legend: {
            display: false,
          },
          zoom: {
            zoom: {
              wheel: {
                enabled: true,
              },
              pinch: {
                enabled: true,
              },
              mode: 'xy',
            },
          },
        },
        color: 'black',
      });

      const totalWeight = tagcloud.reduce((sum, item) => sum + item.weight, 0);

      setData({
        labels: tagcloud.map((tag) => tag.word),
        datasets: [
          {
            data: tagcloud
              .filter((tag) => (tag.weight >= rangedFilter[0] && tag.weight <= rangedFilter[1] ? (tag.weight / totalWeight) * calculateScalingFactor(tag.weight / totalWeight) : 0)).map((tag) => (tag.weight / totalWeight) * calculateScalingFactor(tag.weight / totalWeight)),
          },
        ],
      });
      setComplete(true);
    }
  }, [tagcloud, complete]);

  const resetFilter = () => {
    setRangedFilter([0, Math.max(...tagcloud.map((tag) => tag.weight))]);
    setComplete(false);
  };

  return (
    <>
      <Button onClick={() => setComplete(false)}>{t('common.word.filter')}</Button>
      <Button onClick={resetFilter}>{t('common.word.noFilter')}</Button>
      {complete && <WordCloudComponent options={option} data={data} />}
    </>
  );
}

export default WordCloud;

I tried the solution suggested here https://github.com/chartjs/chartjs-plugin-zoom/issues/64 but nothing changes

kurkle commented 3 hours ago

ChatGPT gave some plausible options. I don't think its number 1 or 4, but it could be 2 or 3

The Chart.js Word Cloud plugin (chartjs-chart-wordcloud) and Chart.js Zoom plugin (chartjs-plugin-zoom) may not work seamlessly together due to the following reasons:

  1. Incompatible Chart Types The chartjs-chart-wordcloud plugin extends Chart.js to support the word cloud chart type, which differs fundamentally from standard chart types like line, bar, or scatter. Word clouds rely on layout algorithms for positioning words, which don’t adhere to Cartesian axes or scales. In contrast, chartjs-plugin-zoom operates primarily on Cartesian axes (e.g., X and Y) to implement panning and zooming.

  2. No Scales in Word Cloud Word clouds don’t utilize traditional scales (x or y) to position elements. Instead, word placement is determined by word frequency, importance, or other metadata, often through custom rendering logic. The zoom plugin depends on scales to modify the viewable area when zooming or panning, which isn't applicable to word clouds.

  3. Rendering Mismatch chartjs-chart-wordcloud uses a different rendering mechanism, which might bypass or conflict with how chartjs-plugin-zoom manages view transformations. For example, chartjs-plugin-zoom manipulates the chartArea and scale transforms, but these adjustments have no effect on a word cloud's rendering algorithm.

  4. Event Handling Differences Zooming and panning rely on mouse or touch events, which are tied to the Chart.js canvas. Word clouds handle events differently, possibly even overriding default behavior to allow word-specific interactivity. This can create conflicts with chartjs-plugin-zoom.

Possible Workarounds If you need to use zooming or panning with word clouds, consider these approaches:

Custom Zoom Implementation: Implement a custom zoom mechanism tailored to your word cloud logic, such as scaling the font sizes and recalculating the layout programmatically.

Integrate Axes or Scales: Modify the word cloud logic to incorporate invisible axes/scales, allowing chartjs-plugin-zoom to work. This might require significant effort and deep customization.