我发现词云特别好用,能迅速构建起一套语言体系。但好像没有很方便的词云生成网站!
效果:词云生成器
需求
- 可以一行一个输入词句,然后会生成对应的词云
- 网站可以自适应页面大小,同时支持上传excel文件,和下载生成的词。
- 词云的结果都是适合中文阅读习惯的,而不是东倒西歪
- 字体颜色不要固定,可以多整几种适合阅读的颜色随机加上去
- 现图片有很大区域是空白的,浪费空间,我要求词云是填满整个页面的
结果
太难整了,不断的调整测试调整测试,感觉还是差很多意思,没有达到我想要的效果。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>词云生成器</title>
<style>
#wordcloud {
width: 100%;
height: 100vh; /* 使词云容器填满整个视口高度 */
overflow: hidden;
}
</style>
</head>
<body>
<h1>词云生成器</h1>
<textarea id="inputWords" rows="10" cols="50" placeholder="请输入词句,每行一个"></textarea>
<br>
<input type="file" id="fileInput" accept=".xlsx,.xls">
<br>
<button onclick="generateWordCloud()">生成词云</button>
<div id="wordcloud"></div>
<a id="downloadLink" style="display: none;">下载词云</a>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/d3-cloud@1/build/d3.layout.cloud.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.16.9/xlsx.full.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.3.2/html2canvas.min.js"></script>
<script>
let currentWords = [];
function generateWordCloud() {
const inputWords = document.getElementById('inputWords').value;
const wordsArray = inputWords.split('\n').filter(word => word.trim() !== '');
const fileInput = document.getElementById('fileInput');
if (fileInput.files.length > 0) {
const file = fileInput.files[0];
const reader = new FileReader();
reader.onload = function(e) {
const data = new Uint8Array(e.target.result);
const workbook = XLSX.read(data, {type: 'array'});
const firstSheetName = workbook.SheetNames[0];
const worksheet = workbook.Sheets[firstSheetName];
const excelData = XLSX.utils.sheet_to_json(worksheet, {header: 1});
const excelWords = excelData.flat().filter(word => word.trim() !== '');
currentWords = [...wordsArray, ...excelWords];
generateCloud(currentWords);
};
reader.readAsArrayBuffer(file);
} else {
currentWords = wordsArray;
generateCloud(currentWords);
}
}
function generateCloud(wordsArray) {
const colors = ["#333", "#666", "#999", "#0066CC", "#009933", "#CC6600"]; // 定义颜色数组
const maxFontSize = 100; // 最大字体大小
const minFontSize = 20; // 最小字体大小,避免字体过小
const fontSizeScale = d3.scaleLinear()
.domain([0, wordsArray.length])
.range([maxFontSize, minFontSize]);
const layout = d3.layout.cloud()
.size([window.innerWidth, window.innerHeight])
.words(wordsArray.map(word => ({text: word, size: fontSizeScale(Math.random() * wordsArray.length)})))
.padding(5)
.rotate(() => 0) // 确保文字不旋转
.font("SimHei") // 使用适合中文的字体
.fontSize(d => d.size)
.on("end", draw);
layout.start();
function draw(words) {
d3.select("#wordcloud").selectAll("*").remove();
const svg = d3.select("#wordcloud")
.append("svg")
.attr("width", layout.size()[0])
.attr("height", layout.size()[1])
.append("g")
.attr("transform", "translate(" + layout.size()[0] / 2 + "," + layout.size()[1] / 2 + ")")
.selectAll("text")
.data(words)
.enter().append("text")
.style("font-size", d => d.size + "px")
.style("font-family", "SimHei") // 使用适合中文的字体
.style("fill", () => colors[Math.floor(Math.random() * colors.length)]) // 随机选择颜色
.attr("text-anchor", "middle")
.attr("transform", d => "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")")
.text(d => d.text);
// 确保词云容器大小与生成的SVG大小一致
document.getElementById('wordcloud').style.width = layout.size()[0] + 'px';
document.getElementById('wordcloud').style.height = layout.size()[1] + 'px';
html2canvas(document.getElementById('wordcloud'), { scale: 2 }).then(canvas => {
const url = canvas.toDataURL("image/png");
document.getElementById('downloadLink').href = url;
document.getElementById('downloadLink').download = "wordcloud.png";
document.getElementById('downloadLink').style.display = 'block';
});
}
}
window.addEventListener('resize', () => generateCloud(currentWords));
</script>
</body>
</html>
解释代码
-
自适应页面大小:
- 使用
window.innerWidth
和window.innerHeight
动态设置词云的大小。 - 添加
window.addEventListener('resize', () => generateCloud(currentWords))
监听窗口大小变化,重新生成词云。
- 使用
-
支持上传Excel文件:
- 使用
FileReader
读取上传的Excel文件。 - 使用
xlsx.js
库解析Excel文件内容,并将其转换为词云所需的格式。
- 使用
-
下载生成的词云:
- 使用
html2canvas
库将生成的SVG词云转换为Canvas元素。 - 设置
html2canvas
的scale
参数为2,以提高图片的分辨率。 - 将Canvas元素转换为PNG图片,并生成下载链接。
- 设置下载链接的
download
属性,以便在点击时自动下载图片。
- 使用
-
适合中文阅读习惯:
- 设置
rotate(() => 0)
确保文字不旋转。 - 使用适合中文的字体
SimHei
(黑体)。
- 设置
-
多样化的字体颜色:
- 定义一个颜色数组
colors
,包含多种适合阅读的颜色。 - 在生成词云时,随机选择颜色数组中的颜色。
- 定义一个颜色数组
-
解除数量限制:
- 通过调整词云生成的逻辑,确保能够处理任意数量的词汇。
-
动态调整字体大小:
- 使用
d3.scaleLinear
动态调整字体大小,以确保更多的词汇能够显示出来。 - 设置最小字体大小为20,避免字体过小而难以辨认。
- 使用
-
避免字体互相遮挡:
- 通过调整词云布局算法,确保字体不会互相遮挡。
-
确保词云容器大小与生成的SVG大小一致:
- 在生成词云后,调整词云容器的宽度和高度,使其与生成的SVG大小一致。
-
填满整个页面:
- 将词云容器的高度设置为
100vh
,使其填满整个视口高度。
- 将词云容器的高度设置为