0

I'm trying to create a word cloud using the @visx/wordCloud library in my React application. However, the rendering time is very slow (about 10 seconds), and I need to create new word clouds on the fly as part of an interactive dashboard, so this delay is problematic.

The sample uses 1000 words and this is the code I am using right now.

import React, { useState, useEffect, useMemo, useCallback, useRef, useLayoutEffect } from 'react';
import { Group } from '@visx/group';
import { Wordcloud } from '@visx/wordcloud';

import { Text } from '@visx/text';




interface LinearScale {
  domain: [number, number];
  range: [number, number];
}
function createLinearScale({ domain, range }: LinearScale)  {
    const [domainMin, domainMax] = domain;
    const [rangeMin, rangeMax] = range;
    const slope = (rangeMax - rangeMin) / (domainMax - domainMin);
    const intercept = rangeMax - slope * domainMax;
    return (x: number) => slope * x + intercept;
  }





type Word = {
  text: string;
  value: number;
};
import data from '../../../data/sample_data/total_wcloud_sample.json'

const randomwords =data

function getRandomRotation() {
  return Math.random() < 0.5 ? 90 : 0; // 50% of words will be rotated by 90 degrees
}

const WordcloudExample = () => {
  const [words, setWords] = useState<Word[]>([]);

const width = 800;
const height = 800;

  useEffect(() => {
    setWords(randomwords);
  }, []);

  const weightScale = useMemo(() =>
  createLinearScale({
    domain: [Math.min(...words.map((w) => w.value)), Math.max(...words.map((w) => w.value))],
    range: [10, 70],
  }),
  [words]
);
const fontSize = useCallback((word: Word) => weightScale(word.value), []);

  return (
    <svg width={width} height={height}>
      <rect x={0} y={0} width={width} height={height} fill="#f8f8f8" />
      <Group >
        <Wordcloud
          words={words}
          fontSize={fontSize}
          width={width}
          height={height}
  
          random={getRandomRotation}
          spiral={'rectangular'}
          //10% should be rotated, 90% should have a rotation of 0
          rotate={ getRandomRotation }
        >
         {(cloudWords) =>
          cloudWords.map((w, i) => (
            <Text

              key={w.text}
              textAnchor={'middle'}
              transform={`translate(${w.x}, ${w.y}) rotate(${w.rotate})`}
              fontSize={w.size}
              fontFamily={w.font}
              fontWeight={w.weight}
              //random color for each word
              fill={`hsl(${Math.random() * 360}, 100%, 50%)`}
            >
                {w.text}
            </Text>
            ))
            }

        </Wordcloud>
      </Group>
    </svg>
  );
};

export default WordcloudExample;

I've tried to optimize the code by using useMemo and useCallback, but it doesn't seem to have much of an effect. I've also created a sample on Codesandbox to show the problem. However, for some reason, the sample on Codesandbox is much faster.

Does anyone have any suggestions for optimizing the rendering time of @visx/wordCloud, or any other word cloud libraries that might be faster? I appreciate any help or advice you can offer. Thank you!

ishan
  • 1

0 Answers0