Added word cloud

This commit is contained in:
Shahan Nedadahandeh 2022-07-04 12:24:12 -07:00
parent 126a61fc28
commit 91ac58ae53
Signed by: snedadah
GPG Key ID: 8638C7F917385B01
6 changed files with 224 additions and 3 deletions

140
components/Wordcloud.tsx Normal file
View File

@ -0,0 +1,140 @@
import { scaleLog } from "@visx/scale";
import { Text } from "@visx/text";
import { Wordcloud as VisxWordcloud } from "@visx/Wordcloud";
import { mockCategoricalData } from "data/mocks";
import React, { useState } from "react";
import { Color } from "utils/Color";
interface ExampleProps {
width: number;
height: number;
showControls?: boolean;
}
export interface WordData {
text: string;
value: number;
}
const colors = [
Color.primaryAccent,
Color.primaryAccentLight,
// Color.primaryAccentLighter,
];
function getWords(): WordData[] {
return mockCategoricalData.map((word) => ({
text: word.key,
value: word.value,
}));
}
function getRotationDegree() {
const rand = Math.random();
const degree = rand > 0.5 ? 60 : -60;
return rand * degree;
}
const words = [...getWords(), ...getWords()];
const fontScale = scaleLog({
domain: [
Math.min(...words.map((w) => w.value)),
Math.max(...words.map((w) => w.value)),
],
range: [10, 100],
});
const fontSizeSetter = (datum: WordData) => fontScale(datum.value);
const fixedValueGenerator = () => 0.5;
type SpiralType = "archimedean" | "rectangular";
export default function Wordcloud({
width,
height,
showControls,
}: ExampleProps) {
const [spiralType, setSpiralType] = useState<SpiralType>("rectangular");
const [withRotation, setWithRotation] = useState(false);
return (
<div className="wordcloud">
<VisxWordcloud
words={words}
width={width}
height={height}
fontSize={fontSizeSetter}
font="Inconsolata"
padding={30}
spiral={spiralType}
rotate={0}
random={fixedValueGenerator}
>
{(cloudWords) =>
cloudWords.map((w, i) => (
<Text
key={w.text}
fill={colors[i % colors.length]}
textAnchor={"middle"}
transform={`translate(${w.x ?? 0}, ${w.y ?? 0})`}
fontSize={w.size}
fontFamily={w.font}
fontWeight={300}
>
{w.text}
</Text>
))
}
</VisxWordcloud>
{showControls && (
<div>
<label>
Spiral type &nbsp;
<select
onChange={(e) => setSpiralType(e.target.value as SpiralType)}
value={spiralType}
>
<option key={"archimedean"} value={"archimedean"}>
archimedean
</option>
<option key={"rectangular"} value={"rectangular"}>
rectangular
</option>
</select>
</label>
<label>
With rotation &nbsp;
<input
type="checkbox"
checked={withRotation}
onChange={() => setWithRotation(!withRotation)}
/>
</label>
<br />
</div>
)}
<style jsx>{`
.wordcloud {
display: flex;
flex-direction: column;
user-select: none;
}
.wordcloud svg {
margin: 1rem 0;
cursor: pointer;
}
.wordcloud label {
display: inline-flex;
align-items: center;
font-size: 14px;
margin-right: 8px;
}
.wordcloud textarea {
min-height: 100px;
}
`}</style>
</div>
);
}

76
package-lock.json generated
View File

@ -11,6 +11,7 @@
"@visx/axis": "^2.10.0",
"@visx/grid": "^2.10.0",
"@visx/shape": "^2.10.0",
"@visx/wordcloud": "^2.10.0",
"next": "12.1.6",
"react": "18.1.0",
"react-dom": "18.1.0"
@ -571,6 +572,19 @@
"integrity": "sha512-WiBSI6JBIhC6LRIsB2Kwh8DsGTlbBU+mLRxJmAe3LjHTdkDpwIbEOZgoXBbZilk/vlfjK8i6nKRAvIRn1XaIMw==",
"dev": true
},
"node_modules/@types/d3": {
"version": "3.5.47",
"resolved": "https://registry.npmjs.org/@types/d3/-/d3-3.5.47.tgz",
"integrity": "sha512-VkWIQoZXLFdcBGe5pdBKJmTU3fmpXvo/KV6ixvTzOMl1yJ2hbTXpfvsziag0kcaerPDwas2T0vxojwQG3YwivQ=="
},
"node_modules/@types/d3-cloud": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/@types/d3-cloud/-/d3-cloud-1.2.5.tgz",
"integrity": "sha512-vEIER9DsEBUOdpRiwCh3n1qE+cV6h4e1LhxhY2sLt+m8LPNAIkOOhTlqk0JDiBwD+ZPM8ynFAOU3AuPuVYBFBA==",
"dependencies": {
"@types/d3": "^3"
}
},
"node_modules/@types/d3-color": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-1.4.2.tgz",
@ -982,6 +996,19 @@
"react": "^16.3.0-0 || ^17.0.0-0 || ^18.0.0-0"
}
},
"node_modules/@visx/wordcloud": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/@visx/wordcloud/-/wordcloud-2.10.0.tgz",
"integrity": "sha512-SN3W9VbnU/qYofPG5xlN0jJWFTMo5v9jlJtWFLgTy9aHV3CtclyyEAQ6/+VPrKWuNR5bgtOSegiE8EJdobrStg==",
"dependencies": {
"@types/d3-cloud": "1.2.5",
"@visx/group": "2.10.0",
"d3-cloud": "^1.2.5"
},
"peerDependencies": {
"react": "^16.8.0-0 || ^17.0.0-0 || ^18.0.0-0"
}
},
"node_modules/acorn": {
"version": "8.7.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz",
@ -1429,11 +1456,24 @@
"internmap": "^1.0.0"
}
},
"node_modules/d3-cloud": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/d3-cloud/-/d3-cloud-1.2.5.tgz",
"integrity": "sha512-4s2hXZgvs0CoUIw31oBAGrHt9Kt/7P9Ik5HIVzISFiWkD0Ga2VLAuO/emO/z1tYIpE7KG2smB4PhMPfFMJpahw==",
"dependencies": {
"d3-dispatch": "^1.0.3"
}
},
"node_modules/d3-color": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz",
"integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q=="
},
"node_modules/d3-dispatch": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.6.tgz",
"integrity": "sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA=="
},
"node_modules/d3-format": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/d3-format/-/d3-format-2.0.0.tgz",
@ -4659,6 +4699,19 @@
"integrity": "sha512-WiBSI6JBIhC6LRIsB2Kwh8DsGTlbBU+mLRxJmAe3LjHTdkDpwIbEOZgoXBbZilk/vlfjK8i6nKRAvIRn1XaIMw==",
"dev": true
},
"@types/d3": {
"version": "3.5.47",
"resolved": "https://registry.npmjs.org/@types/d3/-/d3-3.5.47.tgz",
"integrity": "sha512-VkWIQoZXLFdcBGe5pdBKJmTU3fmpXvo/KV6ixvTzOMl1yJ2hbTXpfvsziag0kcaerPDwas2T0vxojwQG3YwivQ=="
},
"@types/d3-cloud": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/@types/d3-cloud/-/d3-cloud-1.2.5.tgz",
"integrity": "sha512-vEIER9DsEBUOdpRiwCh3n1qE+cV6h4e1LhxhY2sLt+m8LPNAIkOOhTlqk0JDiBwD+ZPM8ynFAOU3AuPuVYBFBA==",
"requires": {
"@types/d3": "^3"
}
},
"@types/d3-color": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-1.4.2.tgz",
@ -4962,6 +5015,16 @@
"reduce-css-calc": "^1.3.0"
}
},
"@visx/wordcloud": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/@visx/wordcloud/-/wordcloud-2.10.0.tgz",
"integrity": "sha512-SN3W9VbnU/qYofPG5xlN0jJWFTMo5v9jlJtWFLgTy9aHV3CtclyyEAQ6/+VPrKWuNR5bgtOSegiE8EJdobrStg==",
"requires": {
"@types/d3-cloud": "1.2.5",
"@visx/group": "2.10.0",
"d3-cloud": "^1.2.5"
}
},
"acorn": {
"version": "8.7.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz",
@ -5254,11 +5317,24 @@
"internmap": "^1.0.0"
}
},
"d3-cloud": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/d3-cloud/-/d3-cloud-1.2.5.tgz",
"integrity": "sha512-4s2hXZgvs0CoUIw31oBAGrHt9Kt/7P9Ik5HIVzISFiWkD0Ga2VLAuO/emO/z1tYIpE7KG2smB4PhMPfFMJpahw==",
"requires": {
"d3-dispatch": "^1.0.3"
}
},
"d3-color": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz",
"integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q=="
},
"d3-dispatch": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.6.tgz",
"integrity": "sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA=="
},
"d3-format": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/d3-format/-/d3-format-2.0.0.tgz",

View File

@ -18,6 +18,7 @@
"@visx/axis": "^2.10.0",
"@visx/grid": "^2.10.0",
"@visx/shape": "^2.10.0",
"@visx/wordcloud": "^2.10.0",
"next": "12.1.6",
"react": "18.1.0",
"react-dom": "18.1.0"

View File

@ -64,7 +64,8 @@ body {
background-color: var(--primary-background);
color: var(--primary-text);
font-family: "Inconsolata", "monospace";
font-family: Inconsolata, monospace;
/* font-family: monospace; */
margin: 0;
}
@ -109,4 +110,4 @@ a:hover {
--card-background: var(--dark--card-background);
--label: var(--dark--label);
}
}
}

View File

@ -77,4 +77,4 @@
src: local(''),
url('../public/fonts/inconsolata-v30-latin-900.woff2') format('woff2'),
url('../public/fonts/inconsolata-v30-latin-900.woff') format('woff'),
}
}

View File

@ -1,5 +1,7 @@
import React from "react";
import Wordcloud from "@/components/Wordcloud";
import { ColorPalette } from "../components/ColorPalette";
export default function Home() {
@ -8,6 +10,7 @@ export default function Home() {
<h1>Playground</h1>
<p>Show off your components here!</p>
<ColorPalette />
<Wordcloud width={2000} height={1000} showControls />
</>
);
}