nolual's picture
Upload 55 files
0c20ea8
import React, { useState } from "react";
import { Text } from "@visx/text";
import { scaleLog } from "@visx/scale";
import Wordcloud from "@visx/wordcloud/lib/Wordcloud";
interface ExampleProps {
demographicWords: string;
width: number;
height: number;
showControls?: boolean;
}
export interface WordData {
text: string;
value: number;
}
export default function CloudWord({
demographicWords,
width,
height,
showControls = true,
}: ExampleProps) {
function wordFreq(text: string): WordData[] {
const words: string[] = text.replace(/\./g, "").split(/\s/);
const freqMap: Record<string, number> = {};
for (const w of words) {
if (!freqMap[w]) freqMap[w] = 0;
freqMap[w] += 1;
}
return Object.keys(freqMap).map((word) => ({
text: word,
value: freqMap[word],
}));
}
function getRotationDegree() {
const rand = Math.random();
const degree = rand > 0.5 ? 60 : -60;
return rand * degree;
}
const words = wordFreq(demographicWords);
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";
// eslint-disable-next-line
const [spiralType, setSpiralType] = useState<SpiralType>("archimedean");
// eslint-disable-next-line
const [withRotation, setWithRotation] = useState(false);
return (
<div className="wordcloud">
<Wordcloud
words={words}
width={width}
height={height}
fontSize={fontSizeSetter}
font={"Impact"}
padding={2}
spiral={spiralType}
rotate={withRotation ? getRotationDegree : 0}
random={fixedValueGenerator}
>
{(cloudWords) =>
cloudWords.map((w, i) => (
<Text
key={w.text}
fill={"#00000"}
textAnchor={"middle"}
transform={`translate(${w.x}, ${w.y}) rotate(${w.rotate})`}
fontSize={w.size}
fontFamily={w.font}
>
{w.text}
</Text>
))
}
</Wordcloud>
<style>{`
.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>
);
}