词云图,是一种文本数据的视觉展示,由词汇组成类似云的彩色图形。
echarts-wordcloud是基于echarts的一个词云库,本篇主要介绍它的使用方法。
安装
npm install echarts
npm install echarts-wordcloud
注意
echarts-wordcloud@2 is for echarts@5
echarts-wordcloud@1 is for echarts@4
引用
import * as echarts from 'echarts';
import 'echarts-wordcloud'
基本配置
-
字体颜色随机展示
看一下echarts-wordcloud的具体配置,我把他封装成了子组件,具体代码如下:
// ChartWordCloud.vue
<template>
<div id="charts-content"></div>
</template>
<script setup lang="ts">
import * as echarts from 'echarts';
import 'echarts-wordcloud';
import { onMounted } from "vue";
// 引入 lodash 中的 merge、深克隆
import merge from 'lodash/merge';
const props = withDefaults(
defineProps<{
options: any
}>(),
{},
)
// 词云图默认属性
const defaultSeries = [{
type: 'wordCloud',
/**
* 绘制词云的形状, 值为回调函数 或 关键字, 默认 circle
* 关键字:
*
* circle(圆形) 词的数量不太多的时候,效果不明显,它会趋向于画一个椭圆
* cardioid(苹果形或心形曲线)
* diamond(菱形 正方形)
* triangle-forward(三角形-向前)
* triangle(三角形-直立)
* pentagon(五边形)
* star(星形)
*/
shape: 'circle',
// 保持 maskImage 的纵横比或形状的纵横比为 1:1
keepAspect: false,
/**
* 词云轮廓图,支持为 HTMLImageElement, HTMLCanvasElement,不支持路径字符串, 不包含白色区域; 可选选项
* shape选项将随着云的形状增长而继续应用
* 有形状限制的时候,最好用背景图来实现,而且这个背景图一定要放base64的,不然词云画不出来
*/
// maskImage: maskImage,
// 词云整个图表放置的位置 和 尺寸大小
left: 'center',
top: 'center',
width: '100%',
height: '100%',
right: null,
bottom: null,
// 词云文本大小范围, 默认为最小12像素,最大60像素
sizeRange: [12, 60],
// 词云文字旋转范围和步长。 文本将通过旋转在[-90,90]范围内随机旋转步骤45
// 如果都设置为 0 , 则是水平显示
rotationRange: [-90, 90],
rotationStep: 45,
/**
* 词间距, 距离越大,单词之间的间距越大, 单位像素
* 这里间距太小的话,会出现大词把小词套住的情况,比如一个大的口字,中间会有比较大的空隙,这时候他会把一些很小的字放在口字里面,这样的话,鼠标就无法选中里面的那个小字
*/
gridSize: 8,
// 设置为true可以使单词部分在画布之外绘制, 允许绘制大于画布大小的单词
drawOutOfBound: false,
/**
* 布局的时候是否有动画
* 注意:禁用时,当单词较多时,将导致UI阻塞。
*/
layoutAnimation: true,
// 这是全局的文字样式,相对应的还可以对每个词设置字体样式
textStyle: {
fontFamily: 'sans-serif',
fontWeight: 'bold',
// 颜色可以用一个函数来返回字符串
color: function () {
// 随机颜色
return (
'rgb(' +
[
Math.round(Math.random() * 160),
Math.round(Math.random() * 160),
Math.round(Math.random() * 160),
].join(',') +
')'
)
},
},
// 鼠标hover的特效样式
emphasis: {
focus: 'self',
textStyle: {
textShadowBlur: 10,
textShadowColor: '#999'
}
},
/**
* 词云数据,必须是一个数组,每个数组项必须有name和value属性
* 设置单个文本的样式: textStyle
*
* 例:{
name: '',
value: 40,
textStyle: {
}
},
*/
data: []
}]
let seriesData = props.options.series;
const series = merge({}, defaultSeries[0], seriesData[0]) // {}表示合并后的新对象,可以传入一个空对象作为初始值
function DrawWordCloud() {
// 词云
let mychart = echarts.init(document.getElementById("charts-content")) // 可以设置主题色'dark'
mychart.setOption({
series: series
})
}
onMounted(() => {
DrawWordCloud()
})
</script>
<style scoped lang="scss"></style>
父组件调用:
<template>
<div class="bestsellers-container">
<chart-word-cloud :options="state.chartOptions"></chart-word-cloud>
</div>
</template>
<script setup lang="ts">
import ChartWordCloud from "./item.vue";
import { onMounted, reactive } from "vue";
const image =
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAA1hJREFUeF7tm01W4zAMgCVzkGEWlFwAht2Ukww9CXCSMichs2PgAqEsJhykFs9OnXHT/MhJ7IaYbOC9Opb1WZZk2UGI/MHI9YcvAH0tIEmuTkHKG/W+BPyGJE/V/4QiF0DvQJRnby8Pffs372k52+0SEIv+iX4aOeqvIPkHTk7yLHtK+8hysgCjNAHcMoXlCgQC/HaFkSwu7zRYIA2Z8eQEmCogLrJYAJTitN2uAXHJGEhTkwLE5vmurY8kuVqSlGsA0DPe88lRiBXHKjoBqJlwmHHOeNXgrrPsKbcbjwR5Tz4BPmw2f1dtg2oE4GNA1kByJLo3pqplSfmPQ69Hm1rgpp9aAJ6VN7L1kgAhUpLysYdiLq80QqgFcH528ThwvbsMLlTbWggHAGaqfGl1r5vn7zbxPQAeHF6o2WXLqTrGEoBnR8QeYIiGuyikE6cSwGLxY+2QdIQYpz8ZROnr28t1CSCm2S/DX5GLpNoCopp9Q2BnBRrA+eJSJSFDUk9/5uqv51xFBAOA/MmZbs/KGWJydnFDiGrzEd2DAPcY5fq3/EDcAAByjNQB/t+QRQ4AYrcAwJnv/jojW9xOkCjFGLbATWagtsa4q8L6Lkl1muIxGiDRSgHwWZA8hl5smShEsReIMRs0lSENIEYrMFWhsiIUWTjUW+G9klhMzrC2JhiNL7DqgXsWEIsvUJ7fPpc8OBiZc4FEFUCqp9PxHI1VTL+sDtdlDbuwqLLD2RRKq6bfCmDnD9RFhVmkyLbXr0546wWJOWyU6ta9DeEYN0TYufrghg3r3g3AOPeDBuvi3AFD+YM8oElIoBsjzjq2vFCmul2ddi4B08Enigxs5dkW8IkgsK/HdYbB1uVQhMep5QjOyjtbwIQtoZfyvQFYG6cpWEJv5QcBmAgEJ4dXt6zZUWCCPmGw8oMtwPYJUtJtsEtWzCSnKwcYDYBZDur7gZEvVh/qMKLyowIorWH82+UlhK6NDWfGq20G+4A6oT52keoUx+VDCC4MLwBGjhCDwlwXCG8ARoLQete/SznO714BDHKOIzu7JhjeAfRxjj6c3dEBMJeE1/XuJRPkrDO7TeOnd4FMPkgY5EBRZ5FS0i/9kaUQKecTN06/rm2C+QDXgYVq/wUgFOmpyvkACUbjkux97g4AAAAASUVORK5CYII=";
const maskImage = new Image();
maskImage.src = image;
console.log(maskImage.src, maskImage);
const state = reactive({
chartOptions: {
series: [
{
gridSize: 20,
sizeRange: [10, 80], // 控制词语的大小范围
rotationRange: [0, 0], // 控制词语的旋转角度范围
rotationStep: 45, // 控制词语旋转的步长
shape: "circle", // 控制词云图的形状,可选值为 'circle', 'cardioid', 'diamond', 'triangle-forward', 'triangle', 'pentagon', 'star'
drawOutOfBound: false, // 控制词云图是否允许词语超出绘制区域
// 布局的时候是否有动画
layoutAnimation: true,
// 图的位置
left: "center",
top: "center",
textStyle: {
fontFamily: "sans-serif",
// fontWeight: 'bold',
color: function () {
return (
"rgb(" +
[
Math.round(Math.random() * 160),
Math.round(Math.random() * 160),
Math.round(Math.random() * 160),
].join(",") +
")"
);
},
},
emphasis: {
focus: 'self',
textStyle: {
fontSize: 20 // 点击的词放大
}
},
// 赋值给series里的词云轮廓图maskImage
data: [
{ name: "互联网服务", value: 1000 },
{ name: "交通运输", value: 850 },
{ name: "公司", value: 800 },
{ name: "军工", value: 600 },
{ name: "医药", value: 900 },
{ name: "商务服务", value: 600 },
{ name: "城乡规划", value: 800 },
{ name: "家政服务", value: 400 },
{ name: "安防", value: 850 },
{ name: "医疗服务", value: 200 },
{ name: "电子科技", value: 8000 },
{ name: "航空航天", value: 1500 },
{ name: "食品饮料", value: 1500 },
{ name: "能源", value: 800 },
{ name: "教育培训", value: 200 },
{ name: "金融", value: 100 },
{ name: "文化娱乐", value: 250 },
{ name: "电力", value: 1200 },
{ name: "石油化工", value: 300 },
{ name: "电子商务", value: 900 },
{ name: "建筑", value: 700 },
{ name: "旅游", value: 550 },
{ name: "环保", value: 750 },
{ name: "地产", value: 1100 },
{ name: "体育", value: 300 },
{ name: "通信", value: 950 },
{ name: "科研", value: 1200 },
{ name: "物流", value: 1300 },
{ name: "咨询", value: 600 },
{ name: "游戏", value: 850 },
{ name: "人力资源", value: 500 },
{ name: "水务", value: 300 },
{ name: "舞蹈艺术", value: 150 },
{ name: "汽车制造", value: 1100 },
{ name: "电影制作", value: 350 },
{ name: "游乐园", value: 250 },
{ name: "新能源", value: 900 },
{ name: "服装设计", value: 400 },
{ name: "采矿", value: 700 },
{ name: "信息安全", value: 800 },
{ name: "化妆品", value: 600 },
{ name: "音乐产业", value: 750 },
{ name: "物联网", value: 1200 },
{ name: "绿色建筑", value: 850 },
{ name: "社交媒体", value: 950 },
{ name: "人工智能", value: 1000 },
{ name: "水产养殖", value: 320 },
{ name: "医学研究", value: 1800 },
{ name: "动物保护", value: 130 },
{ name: "航海", value: 1000 },
],
},
],
},
});
onMounted(() => {});
</script>
<style scoped>
.bestsellers-container {
height: 38.56rem;
background: #f0f0f0;
}
#charts-content {
/* 需要设置宽高后才会显示 */
width: 100%;
height: 100%;
}
</style>
以上是效果
-
字体平行且按预设颜色数组展示
- 实现字体平行且按预设颜色数组展示的效果,只需将rotationRange都设为0即可,再传入自定义的color数组:
// 父组件
chartOptions: {
color: ['#FFFFFF', '#FFFFFF', '#FFFFFF', 'rgba(255,255,255,0.7)', 'rgba(255,255,255,0.5)'],
series: [
{
rotationRange: [0, 0],
gridSize: 45,
sizeRange: [15, 35],
data: [...],
},
],
},
子组件则需要相对应的把将color改为:
color: function (v: any) {
// 根据dataIndex属性作为下标去访问定义的color色系数组
return `${props.options.color[v.dataIndex]}`
}
背景图插入方式:
background: url('../assets/images/bg-cloud.png') repeat center center / cover;
-
自定义展示形状
首先要找到一张图片,为了成功率较高,一定要是矢量图,图片可以去iconfont图标库里找
需要把图片转成base64,不然词云画不出来,推荐一个免费转换的网址Base64图片转换
把图片相关的配置项修改一下
const image = 'data:image/png;base64,...'
const maskImage = new Image();
maskImage.src = image
// 赋值给series里的词云轮廓图maskImage
maskImage: maskImage,
标签:name,value,wordcloud,词云,maskImage,vue3,echarts,Math
From: https://blog.csdn.net/lele66688888/article/details/142975250