diff --git a/CHANGELOG.md b/CHANGELOG.md index afd40a9..0f84b17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,11 +3,22 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.0.3](https://github.com/chrisrzhou/react-wordcloud/compare/v1.0.2...v1.0.3) (2019-03-14) + +Bug fixes + +- https://github.com/chrisrzhou/react-wordcloud/issues/5 +- https://github.com/chrisrzhou/react-wordcloud/issues/11 + +Tooltip bug is fixed by programmatically creating and destroying the `tippy` instance. Word implosion and missing words are related to https://github.com/jasondavies/d3-cloud/issues/36, and is fixed with a recursive solution. + ## [1.0.2](https://github.com/chrisrzhou/react-wordcloud/compare/v1.0.1...v1.0.2) (2019-03-06) + Thanks to @warlock for transferring the NPM `react-wordcloud` to me! Updating `package.json` and pushing package to NPM. ## [1.0.1](https://github.com/chrisrzhou/react-wordcloud/compare/v1.0.0...v1.0.1) (2019-03-06) + Change `word.count` to `word.key` because the weight of the word could be a float. ## [1.0.0](https://github.com/chrisrzhou/react-wordcloud/compare/v0.1.1...v1.0.0) (2019-03-03) diff --git a/package.json b/package.json index c31e9cb..093d7ab 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-wordcloud", - "version": "1.0.2", + "version": "1.0.3", "description": "Simple React + D3 wordcloud component with powerful features.", "main": "dist/index.js", "module": "dist/index.module.js", diff --git a/src/index.tsx b/src/index.tsx index bcd2a46..0411c98 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -82,16 +82,31 @@ function Wordcloud({ .spiral(spiral) .text(getText) .font(fontFamily) - .fontSize((word: Word) => { - const fontScale = getFontScale(words, fontSizes, scale); - return fontScale(word.value); - }) .fontStyle(fontStyle) - .fontWeight(fontWeight) - .on('end', () => { - render(selection, sortedWords, mergedOptions, mergedCallbacks); - }) - .start(); + .fontWeight(fontWeight); + + const draw = (fontSizes: MinMaxPair): void => { + layout + .fontSize((word: Word) => { + const fontScale = getFontScale(words, fontSizes, scale); + return fontScale(word.value); + }) + .on('end', output => { + if (words.length !== output.length) { + // https://github.com/jasondavies/d3-cloud/issues/36 + // recursively draw and decrease maxFontSize by minFontSize. + // Ensure that minFontSize is at least of value '1' + const minFontSize = fontSizes[0] || 1; + const maxFontSize = fontSizes[1] - fontSizes[0]; + draw([minFontSize, maxFontSize]); + return; + } else { + render(selection, sortedWords, mergedOptions, mergedCallbacks); + } + }) + .start(); + }; + draw(fontSizes); } }, [callbacks, maxWords, options, selection, size, words]); diff --git a/src/render.ts b/src/render.ts index 1d8cdd8..a0f3a49 100644 --- a/src/render.ts +++ b/src/render.ts @@ -1,9 +1,10 @@ -import tippy from 'tippy.js'; +import * as d3 from 'd3'; +import tippy, { Instance } from 'tippy.js'; import { Callbacks, Options, Selection, Word } from './types'; import { choose, getFontSize, getText, getTransform } from './utils'; -const TIPPY_CLASS = 'react-wordcloud-word'; +let tooltipInstance: Instance; export default function render( selection: Selection, @@ -33,10 +34,24 @@ export default function render( .enter() .append('text') .on('click', onWordClick) - .on('mouseover', onWordMouseOver) - .on('mouseout', onWordMouseOut) - .attr('data-tippy-content', getWordTooltip) - .attr('class', TIPPY_CLASS) + .on('mouseover', word => { + if (enableTooltip) { + tooltipInstance = tippy(d3.event.target, { + animation: 'scale', + arrow: true, + content: () => { + return getWordTooltip(word); + }, + }) as Instance; + } + onWordMouseOver && onWordMouseOver(word); + }) + .on('mouseout', word => { + if (tooltipInstance) { + tooltipInstance.destroy(); + } + onWordMouseOut && onWordMouseOut(word); + }) .attr('cursor', onWordClick ? 'pointer' : 'default') .attr('fill', getFill) .attr('font-family', fontFamily) @@ -67,8 +82,4 @@ export default function render( .duration(transitionDuration) .attr('fill-opacity', 0) .remove(); - - if (enableTooltip) { - tippy(`.${TIPPY_CLASS}`, { animation: 'scale', arrow: true }); - } }