UNPKG

react-d3-cloud

Version:

A word cloud component using d3-cloud

210 lines (167 loc) 10.9 kB
# react-d3-cloud [![npm version](https://badge.fury.io/js/react-d3-cloud.svg)](https://badge.fury.io/js/react-d3-cloud) [![Build Status](https://github.com/Yoctol/react-d3-cloud/workflows/CI/badge.svg?branch=master)](https://github.com/Yoctol/react-d3-cloud/actions?query=branch%3Amaster) A word cloud react component built with [d3-cloud](https://github.com/jasondavies/d3-cloud). ![image](https://cloud.githubusercontent.com/assets/6868283/20619528/fa83334c-b32f-11e6-81dd-6fe4fa6c52d9.png) ## Installation ```sh npm install react-d3-cloud ``` ## Usage Simple: ```jsx import React from 'react'; import { render } from 'react-dom'; import WordCloud from 'react-d3-cloud'; const data = [ { text: 'Hey', value: 1000 }, { text: 'lol', value: 200 }, { text: 'first impression', value: 800 }, { text: 'very cool', value: 1000000 }, { text: 'duck', value: 10 }, ]; render(<WordCloud data={data} />, document.getElementById('root')); ``` More configuration: ```jsx import React from 'react'; import { render } from 'react-dom'; import WordCloud from 'react-d3-cloud'; import { scaleOrdinal } from 'd3-scale'; import { schemeCategory10 } from 'd3-scale-chromatic'; const data = [ { text: 'Hey', value: 1000 }, { text: 'lol', value: 200 }, { text: 'first impression', value: 800 }, { text: 'very cool', value: 1000000 }, { text: 'duck', value: 10 }, ]; const schemeCategory10ScaleOrdinal = scaleOrdinal(schemeCategory10); render( <WordCloud data={data} width={500} height={500} font="Times" fontStyle="italic" fontWeight="bold" fontSize={(word) => Math.log2(word.value) * 5} spiral="rectangular" rotate={(word) => word.value % 360} padding={5} random={Math.random} fill={(d, i) => schemeCategory10ScaleOrdinal(i)} onWordClick={(event, d) => { console.log(`onWordClick: ${d.text}`); }} onWordMouseOver={(event, d) => { console.log(`onWordMouseOver: ${d.text}`); }} onWordMouseOut={(event, d) => { console.log(`onWordMouseOut: ${d.text}`); }} />, document.getElementById('root') ); ``` Please checkout [demo](https://codesandbox.io/embed/react-d3-cloud-demo-forked-50wzl) for more detailed props, please refer to below: ## Props | name | description | type | required | default | | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- | -------- | ------------------------------------------- | | data | The words array | `{ text: string, value: number }>[]` | ✓ | | width | Width of the layout (px) | `number` | | `700` | | height | Height of the layout (px) | `number` | | `600` | | font | The font accessor function, which indicates the font face for each word. A constant may be specified instead of a function. | `string \| (d) => string` | | `'serif'` | | fontStyle | The fontStyle accessor function, which indicates the font style for each word. A constant may be specified instead of a function. | `string \| (d) => string` | | `'normal'` | | fontWeight | The fontWeight accessor function, which indicates the font weight for each word. A constant may be specified instead of a function. | `string \| number \| (d) => string \| number` | | `'normal'` | | fontSize | The fontSize accessor function, which indicates the numerical font size for each word. | `(d) => number` | | `(d) => Math.sqrt(d.value)` | | rotate | The rotate accessor function, which indicates the rotation angle (in degrees) for each word. | `(d) => number` | | `() => (~~(Math.random() * 6) - 3) * 30` | | spiral | The current type of spiral used for positioning words. This can either be one of the two built-in spirals, "archimedean" and "rectangular", or an arbitrary spiral generator can be used | `'archimedean' \| 'rectangular' \| ([width, height]) => t => [x, y]` | | `'archimedean'` | | padding | The padding accessor function, which indicates the numerical padding for each word. | `number \| (d) => number` | | `1` | | random | The internal random number generator, used for selecting the initial position of each word, and the clockwise/counterclockwise direction of the spiral for each word. This should return a number in the range `[0, 1)`. | `(d) => number` | | `Math.random` | | fill | The fill accessor function, which indicates the color for each word. | `(d, i) => string` | | `(d, i) => schemeCategory10ScaleOrdinal(i)` | | onWordClick | The function will be called when `click` event is triggered on a word | `(event, d) => {}` | | null | | onWordMouseOver | The function will be called when `mouseover` event is triggered on a word | `(event, d) => {}` | | null | | onWordMouseOut | The function will be called when `mouseout` event is triggered on a word | `(event, d) => {}` | | null | ## FAQ ### How to Use with Next.js/SSR To make `<WordCloud />` work with Server-Side Rendering (SSR), you need to avoid rendering it on the server: ```js { typeof window !== 'undefiend' && <WordCloud data={data} />; } ``` ### How to Avoid Unnecessary Re-render As of version 0.10.1, `<WordCloud />` has been wrapped by `React.memo()` and deep equal comparison under the hood to avoid unnecessary re-render. All you need to do is to make your function props deep equal comparable using `useCallback()`: ```js import React, { useCallback } from 'react'; import { render } from 'react-dom'; import WordCloud from 'react-d3-cloud'; import { scaleOrdinal } from 'd3-scale'; import { schemeCategory10 } from 'd3-scale-chromatic'; function App() { const data = [ { text: 'Hey', value: 1000 }, { text: 'lol', value: 200 }, { text: 'first impression', value: 800 }, { text: 'very cool', value: 1000000 }, { text: 'duck', value: 10 }, ]; const fontSize = useCallback((word) => Math.log2(word.value) * 5, []); const rotate = useCallback((word) => word.value % 360, []); const fill = useCallback((d, i) => scaleOrdinal(schemeCategory10)(i), []); const onWordClick = useCallback((word) => { console.log(`onWordClick: ${word}`); }, []); const onWordMouseOver = useCallback((word) => { console.log(`onWordMouseOver: ${word}`); }, []); const onWordMouseOut = useCallback((word) => { console.log(`onWordMouseOut: ${word}`); }, []); return ( <WordCloud data={data} width={500} height={500} font="Times" fontStyle="italic" fontWeight="bold" fontSize={fontSize} spiral="rectangular" rotate={rotate} padding={5} random={Math.random} fill={fill} onWordClick={onWordClick} onWordMouseOver={onWordMouseOver} onWordMouseOut={onWordMouseOut} /> ); ); ``` ## Build ```sh npm run build ``` ## Test ### pre-install #### Mac OS X ```sh brew install pkg-config cairo pango libpng jpeg giflib librsvg npm install ``` #### Ubuntu and Other Debian Based Systems ```sh sudo apt-get update sudo apt-get install libcairo2-dev libjpeg8-dev libpango1.0-dev libgif-dev build-essential g++ npm install ``` For more details, please check out [Installation guides](https://github.com/Automattic/node-canvas/wiki) at node-canvas wiki. ### Run Tests ```sh npm test ``` ## License MIT © [Yoctol](https://github.com/Yoctol/react-d3-cloud)