写在开头
哈喽啊,各位UU早上好吖!☀
先给大家来个才艺,跳段街舞:ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ (来自沸点的编舞)😆
这两周工作比较忙都没空上来写"水文"😪,好在熬过去了,接下来应该能空闲一些,摸鱼,启动。🐟
今天一早刷到个新闻:
童年的回忆,这是...又能看几个铁壳子打架了?😂 就是不知道女警还...Em...还能不能看。😗
回到正题,本文将分享关于词云图的内容,请诸君按需食用。
下载安装
本次分享的词云图功能小编是通过 echarts-wordcloud 这个包来实现的,它是基于 wordcloud2.js 实现的一个 echarts 第三方扩展包。
如果你项目中没有使用 echarts 的话,单纯想使用词云图功能,那么你可以直接去使用 wordcloud 包即可。
echarts-wordcloud 说明文档:传送门。
echarts-wordcloud 其他案例预览:传送门。
wordcloud2.js 官网:传送门。
npm install echarts@5.4.3
npm install echarts-wordcloud
不知道你注意到没有,小编下载的 echarts 包版本是 5.4.3 ,为什么要写死这个版本呢?
截止到写这篇文章2024年05月24日,echarts 默认通过 npm install 下载的版本是 5.5.0,但用最新版本的 echarts 却渲染不出来词云图,遇到如下报错:
是新版本的 echarts 还没兼容好❓
小编降级了两个小版本 5.4.3 与 5.4.2 倒是都可以使用✅,就先使用低一点的版本吧,问题不大,注意一点就好。
echarts-wordcloud1.x对应echarts4.x
echarts-wordcloud2.x对应echarts5.x
基本使用
咱们先跟着文档初始化一个基础效果出来玩玩。🤠
<template>
<div class="container" ref="container"></div>
</template>
<script>
import * as echarts from 'echarts';
import 'echarts-wordcloud';
export default {
data() {
return {
_chart: null,
_options: {
series: [
{
type: 'wordCloud',
width: '70%',
height: '70%',
left: 'center',
top: 'center',
right: null,
bottom: null,
// 形状
shape: 'circle',
// 文字之间的间距
gridSize: 0,
// 字体大小范围
sizeRange: [5, 18],
// 文字旋转角度范围
rotationRange: [-90, 90],
// 步长, 在[-90, 90]范围内随机旋转,-90/-45/0/45/90
rotationStep: 45,
// 是否渲染超出画布的文字
drawOutOfBound: false,
// 数据
data: [],
// 渲染时有动画效果,如果数据量大的数据,设置该配置能避免长时间空白
layoutAnimation: true,
// 自动缩放文本
shrinkToFit: true,
// 词云图-全局样式
textStyle: {},
},
],
},
}
},
mounted() {
this.initChart();
},
methods: {
/** @name 初始化 **/
initChart() {
this.$nextTick(() => {
if (this._chart) this._chart.dispose();
if (this.$refs?.container)
this._chart = echarts.init(this.$refs?.container);
if (!this._chart) return;
this._chart.clear();
this.setOptions();
});
},
setOptions() {
if (!this._chart) return;
const seriesItem = this._data._options.series[0];
// 数据
seriesItem.data = [
{"name":"潮州","value":146765},
{"name":"惠州","value":112179}
// ...
];
this._chart.clear();
this._chart.setOption(this._data._options, { notMerge: true });
}
}
}
</script>
<style scoped>
.container {
width: 600px;
height: 400px;
border: 1px solid #ccc;
}
</style>
效果:
(不圆不方的形状😪)
数据上面就简列了两个,你可以按着格式扩充就行。
🔉如果你在使用中遇到安装是正常的,使用方式也是正确的,但页面就是没有渲染出东西,并且控制台也没有报错。
那你可以看看
DOM结构,有没有相关的canvas元素渲染。如果没有,那你可以尝试将导入
import 'echarts-wordcloud';改成
import 'echarts-wordcloud/dist/echarts-wordcloud.min.js';或者直接改成
CDN的形式引入。这坑很奇怪,不知道为啥,反正小编我踩过了🤢,记录一下。
形状
词云图,通常我们希望的是它能够变化出多种多样的形状,这无疑是咱们最为期待的一项功能。😛
从上述配置中我们可以观察到,词云图的形状可以通过 shape 属性进行设定。根据官方文档的说明,它支持以下几种形状:
circle:圆形(默认)。cardioid:心形。diamond:菱形。triangle-forward:三角形向前。triangle:三角形。pentagon:五边形。star:五角星。
不错,还支持挺多形状的,足够满足小编的需求了,开心。😊
然而,当小编开开心心做这个"感觉很简单"功能的时候,就开始要倒大霉了。
主要存在两个问题:
- 形状不像,如果是容器尺寸适中,数据量也适宜,某些形状还能接受,但是心形看起来简直惨不忍睹。。😓
- 容器大小变化时,形状完全乱套了。由于小编的业务中,容器尺寸能够随意缩放大小,所以这无疑也是一个问题。
怎么搞呢❓❓❓
在 echarts-wordcloud 还提供了一个 maskImage 属性,它允许你提供一个图像,它会从绘图文本中排除白色区域的轮廓图像。(就是说会根据你提供的图片进行绘制😮)
但在 wordcloud2.js 文档中并没有这个属性哦,不过应该也能进行扩展,毕竟
echarts-wordcloud是在它的基础上扩展出来的。
而这个图片,你可以去 iconfont 上随意下载 .png 图片。
需要注意一点的是,图片内容区部分必须是纯黑色(#000000)的,这点很重要❗❗❗否则可能啥也没渲染出来哦。😗
具体使用:
<script>
...
import shape from './shape';
export default {
data() {
return {
...,
shape: 'circle',
}
},
computed: {
shapeOptions() {
return [
{ label: '圆形', value: 'circle' },
{ label: '椭圆', value: 'ellipse' },
{ label: '五角星', value: 'star' },
{ label: '菱形', value: 'diamond' },
{ label: '三角形', value: 'triangleTop' },
{ label: '正方形', value: 'square' },
{ label: '长方形', value: 'rectangle' },
{ label: '箭头', value: 'arrowRight' },
];
}
},
methods: {
...,
setOptions() {
if (!this._chart) return;
const seriesItem = this._data._options.series[0];
seriesItem.data = data;
// 保持maskImage属性的图像横纵比例
seriesItem.keepAspect = true;
// 形状
const shapeConfig = shape[this.shape];
const maskImage = new Image();
maskImage.src = shapeConfig.img;
maskImage.onload = () => {
seriesItem.maskImage = maskImage;
this._chart.clear();
this._chart.setOption(this._data._options, { notMerge: true });
};
}
}
}
</script>
keepAspect 属性能帮咱们保持图像的比例,可以解决容器变化大小时,形状乱套的问题。
keepAspect属性仅echarts-wordcloud@2.1.0版本支持。
通过 iconfont 下载的 .png 图片,还需要将其转成base64才能使用。
下面小编提供了几个形状的 base64 数据,你也可以自己再增加。
shape.js 文件:
/**@name 五角星 **/
const star = {
shape: 'star',
img:
'data:image/png;base64,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',
};
/**@name 菱形 **/
const diamond = {
shape: 'diamond',
img:
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAAAXNSR0IArs4c6QAAA+tJREFUeF7t3Uly3EAMRFHqzLZPYfvOjpbVUneLQw1AIZFIbhjBHeo/DhtGvW06Sq/AW+npt+3nx/x/qq5DZQC3+L8/wv/atq0kgqoAHuPfb/6SCCoC2ItfFkE1AGfxSyKoBKAlfjkEVQD0xC+FoAKAkfhlELADmIlfAgEzAIv49AhYAVjGp0bACMAjPi0CNgCe8SkRMAFYEZ8OAQuAlfGpEDAAiIhPgyA7gMj4FAgyA0CInx5BVgBI8VMjyAgAMX5aBNkAIMdPiSATgAzx0yHIAiBT/FQIMgDIGD8NAnQAmeOnQIAMgCE+PAJUAEzxoREgAmCMD4sADQBzfEgESAAqxIdDgAKgUnwoBAgAKsaHQRANoHJ8CASRABT/TmDbwn5NjwKg+F/xQ58EEQAU/3v8MASrASj+cfwQBCsBKP51/OUIVgFQ/Pb4SxGsAKD4/fGXIfAGoPjj8Zcg8ASg+PPx3RF4AVB8u/iuCDwAKL59fDcE1gAU3y++CwJLAIrvH98cgRUAxV8X3xSBBQDFXx/fDMEsAMWPi2+CYAaA4sfHn0YwCkDxceJPIRgBoPh48YcR9AJQfNz4Qwh6ACg+fvxuBK0AFD9P/C4ELQAUP1/8ZgRXABQ/b/wmBGcAFD9//EsERwAUnyf+KYI9AIrPF/8QwSsAxeeNv4vgEYDi88f/huAOQPHrxH9CcAfwo+ru2fW6f058u+n/Pr4ChKCOhvf4t3FfPwKFgB/BZ/w9ALdrQsCL4Cn+EQAh4ATwLf4ZACHgQrAb/wqAEHAgOIzfAkAIciM4jd8KQAhyIriM3wNACHIhaIrfC0AIciBojj8CQAiwEXTFHwUgBJgIuuPPABACLARD8WcBCAEGguH4FgCEIBbBVHwrAEIQg2A6viUAIViLwCS+NQAhWIPALL4HACHwRWAa3wuAEPggMI/vCUAIbBG4xPcGIAQ2CNzirwAgBHMIXOOvAiAEYwjc468EIAR9CJbEXw1ACNoQLIsfAUAIzhEsjR8FQAj2ESyPHwlACJ4RhMSPBiAE/xGExUcAUB1BaHwUAFURhMdHAlANAUR8NABVEMDERwTAjgAqPioAVgRw8ZEBsCGAjI8OgAUBbPwMALIjgI6fBUBWBPDxMwHIhiBF/GwAsiBIEz8jAHQEqeJnBYCKIF38zADQEKSMnx0ACoK08RkARCNIHZ8FQBSC9PGZAKxGQBGfDcAqBDTxGQF4I6CKzwrACwFdfGYA1ggo47MDsEJAG78CgFkE1PGrABhFQB+/EoBeBCXiVwPQiqBM/IoArhCUil8VwBGCcvErA3hFUDJ+dQB3BLfz+0bKFY/XzaMrrkHpmf8BZSX6gcDcCB4AAAAASUVORK5CYII=',
};
/**@name 圆形 **/
const circle = {
shape: 'circle',
img:
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAAAXNSR0IArs4c6QAACPtJREFUeF7tnTvsFUUUxn8YKizAEJTCaAERAUlEwBjRgkR8RAWfhVYaolL54l0RKuVlxAohRCspEJ8QXwWFjxBAIVERDRYSE1FjhEIrgu533cX7v9y7d/Yxe3d3ziQ3+RfzOOc73393Z+abM+NoZ7kGmAFMB64GrgSmApOBSfHf/Tw/DZwB/gD098/AT8BJ4Hvgh7bBNa4FDl0FLARuAuYD1wMTPPn1N3AMOAIcBD4HTnkaq5Jum0qAO6MA6HcbMLsSpAYPcjwi4CcRAT+MfyM2J9vwTSLA3cBDwP3AxGxuVlZbr493gDeB/ZWNWmCguhNA7/HHgGXAlAJ+jqLp78Au4PX4+2EUNgwds64EuAN4Kv5vH+pEAyroqbAd+KhuttaNAA9GX+HPArfUDaiS7PkM2Ba/Ikrqslg3dSHAPcCaFge+N0qaPbwYzVr2FQtf8dajJsBcYD2wtLgrjezhXWBD5P/RUVk/KgJcArwArB6V4zUbdxOwDjhftV2jIMASYDOg1Tor/yOgVcZVwHtVglI1AfQB9HSVDjZwrFeAZ6qyuyoCLIinQTdU5VjDx/kq2otYDhz27UcVBHgC2OHbkZb2/ySw06dvvgmwBVjh04EA+t4KrPTlpy8CjI+2Y3fHa/e+bA+pX+0tPAKcK9tpHwS4Il7pautqXtkxcO1Pq4gPxzoF1zZD65VNgGnA28CcoSNbhTwIfB3vj/yYp3G/NmUSQDt3WtqUCseKPwSkTtLSuRRKhUtZBNB/vgQRFvzCIXHqQCSQIKbwk6AMAkhr97E99p0CV2YlvQ4WA78W6bQoAfS1fyCgXbwiWPtoqw/DRUVmB0UJsMemej7imqlPTRE1O8hVihDAFnlyQe6lUe7ForwEsOVdL3Es1GmuZeM8BNDGzqFCplpjXwjcmHUDKQ8Bvoz2rG1Xz1cIi/WrXcR5WbrISgDbz8+C7mjqZtITZCGAlDzSsFmpPwLSWDopi1wJIA3fdybjqn/kYwslL5vpojF0JcBGE3A2JviJoRKaSmqfWlwIIOm2Pi6sNA8BfaynSs5dCKBjTaHq9psX8rEW65vtvjQnhhFA247vNx2FwO2/N+0E0jACaLNByResNBcBxfDWQeanEUBn8bXZY6X5CCiWe/u5kUaAT22bt/mRjz0Y+BQYRACdz5fCx0p7EJCC6KL8BIMIIGFn6tdje3AJxhPF9IFeb/sRQOLOE8HAEpaj1/aKSfsRQMe214aFSzDeKimFjqFfKP0I8FsDEzIFE8GCjipx1eVpBFAqtpGnLSnopDVPR0CLexdS2PU+AV6L07IZiO1FQGnrHk/c6yXAn3Eu3fa6b56d7Y5xNwE0T/zA8AkCgbuSdZ5uArxcZWqSIGCur5OS9ikfI90E+BaYVV+bzbISEVCsr+smgFKuKy++lXAQ0D0Kp5IngLJPvBGO7+ZpdPnFo8rikhDA5N7hcaIjH08IoNy1N4eHQdAefyGxT0KAvzxesxI0yjV2XtffXCoCKGVrKelGauysmdYfgRkigESDTqdIDMXWIbBEBHgOeKl1rplDLgg8LwLYCqALVO2ss00EUIoRXdViJTwE9ooApv0PL/CJx5+LADr1K62YlfAQOCEC/JJyl254kITl8WkR4J+wfDZvuxEwAgTOByOAEcBeASFzwJ4AIUc/loTZR2DAJLBpYMDB1/UzthAUNgE6C0G2FBwuCTpLwbYZFC4BOptBth0cLgE628EmCAmXAB1BiEnCwiVARxJmotBwCdARhaqYLDw8ElyQhct1OxgSHgHGHAyxo2HhEWDM0TA7HBoeAcYcDrXj4eERYMzxcLn/TZQcenZ4OATp8fEk1pYiJsj40zdFjCWJCocMfZNEyf0zwMRwcAjSU8X4ssRzSxQZHgdSE0Vaqtj2EyI1Vazct2TR7SXB0GTRct3SxbeXAE7p4u3CiPYSwOnCCLn/FnB/e3EI0jNdAHpRTHtnAQkydmlU+ziS6dIouW/XxrWHBJmvjZPrShsjxbCV5iPw8KBYDnoFJC7bU6D5wZfY55ZBbgwjgF0e3XwCFLo8Wu7b9fHNJUHh6+Pl+lzgq+ZiELTlNwBH0xAY9gpI2m4EVgcNZfOc3wSsGWa2KwEuidPJ6QyBlfoj8AMwEzg/zFRXAqifJdHrQO8UK/VHYKlrAvAsBJDbJh+vf/A7cm9XM7MSQP1+GbFLHxdW6oeAPtbnZTErDwEWAIeyDGJ1K0PgRuBwltHyEED9PwHsyDKQ1fWOwJPAzqyj5CWAxtkCrMg6oNX3gsBWYGWenosQQOPtiQ6UPJRnYGtTGgLasNNmT65SlADjgQNpmw25rLJGrghom3cRcM61QW+9ogRQf1dE9899AszJa4S1y4XA18DtyvWXq3XcqAwCqKtp8XXk04sYY22dETgJSOHzo3OLARXLIoC6l5h0H2AkKBqV9PYKvrbpS7nrsUwCJE+Ct+114I0BeuxL2Fn4Pz+xsGwCqN+p8exgoArFGzzt7lgffJpx/Vqmmz4IIPs0O9htU8TSQqWpnrK45P7aH2SJLwIk49liUXEO5F7kcRnaNwFkgy0bu0Sif51cy7tZhquCALJHG0jbbRfROTTa1VuedWPHufeuilURIBnS9ATDo5RpP394d+k1qiaArJGyaHOcorao/W1qLxnXKlclT1mOj4IAsl0aQx1DN6Hpf5GUgHOdi4avrMD7XAfIYqMk5+sj6bI0bCEWaSw3DJNu+wRmVE+AXp+0tLk22lRa6NPZGvWtRR1J7bV0PtJSFwIkIGilS4LGtq4iKvC6oWXvSKM+wlmAq9/KT6Bp0H2uDWpeT/sjrwIf1c3Ouj0BevHRDuNjwDJgSt3AG2KPEjLtApSWrZSdOx/+150A3T4rhZ1eEXoqTPIBRgl9ngX03661+/0l9Oe9iyYRoBsMiSH0WwzM8o5S+gBKvCxF1Ifxb8TmZBu+qQTo9lKp7jV7uCn6qp4fHWe/PppXT8gGg3NtXbNyLBJkHIkIeDC+aeWUc+saVmwDAfrBqkOs+n6QOkl58a+MdQqT49eHNAv9ivR1yqX7R6y1+xn4CZAKR+9xrda1qvwLzSczzi0YOZMAAAAASUVORK5CYII=',
};
/**@name 三角形 **/
const triangleTop = {
shape: 'triangle',
img:
'data:image/png;base64,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',
};
/**@name 正方形 **/
const square = {
shape: function shapeSquare(theta) {
return Math.min(
1 / Math.abs(Math.cos(theta)),
1 / Math.abs(Math.sin(theta)),
);
},
img:
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAAAXNSR0IArs4c6QAAAq9JREFUeF7tlMENgDAQw2D/oWEDfBIf8Jl3JBrH7Xn0rSZwrm5f+SMBlkuQAAmwnMDy+r0ACbCcwPL6vQAJgAQuTBT4MoHHSz55ARLgy/Py2RKAGakTCaCel8slADNSJxJAPS+XSwBmpE4kgHpeLpcAzEidSAD1vFwuAZiROpEA6nm5XAIwI3UiAdTzcrkEYEbqRAKo5+VyCcCM1IkEUM/L5RKAGakTCaCel8slADNSJxJAPS+XSwBmpE4kgHpeLpcAzEidSAD1vFwuAZiROpEA6nm5XAIwI3UiAdTzcrkEYEbqRAKo5+VyCcCM1IkEUM/L5RKAGakTCaCel8slADNSJxJAPS+XSwBmpE4kgHpeLpcAzEidSAD1vFwuAZiROpEA6nm5XAIwI3UiAdTzcrkEYEbqRAKo5+VyCcCM1IkEUM/L5RKAGakTCaCel8slADNSJxJAPS+XSwBmpE4kgHpeLpcAzEidSAD1vFwuAZiROpEA6nm5XAIwI3UiAdTzcrkEYEbqRAKo5+VyCcCM1IkEUM/L5RKAGakTCaCel8slADNSJxJAPS+XSwBmpE4kgHpeLpcAzEidSAD1vFwuAZiROpEA6nm5XAIwI3UiAdTzcrkEYEbqRAKo5+VyCcCM1IkEUM/L5RKAGakTCaCel8slADNSJxJAPS+XSwBmpE4kgHpeLpcAzEidSAD1vFwuAZiROpEA6nm5XAIwI3UiAdTzcrkEYEbqRAKo5+VyCcCM1IkEUM/L5RKAGakTCaCel8slADNSJxJAPS+XSwBmpE4kgHpeLpcAzEidSAD1vFwuAZiROpEA6nm5XAIwI3UiAdTzcrkEYEbqRAKo5+VyrwXgX5T4LYFHO37bqoOPCSTAGJUzmADOXcetEmCMyhlMAOeu41YJMEblDCaAc9dxqxuoAHCBGZfSZgAAAABJRU5ErkJggg==',
};
/**@name 长方形 **/
const rectangle = {
shape: function shapeSquare(theta) {
return Math.min(
1 / Math.abs(Math.cos(theta)),
1 / Math.abs(Math.sin(theta)),
);
},
img:
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAANoAAACACAYAAABtCHdKAAAAAXNSR0IArs4c6QAAA09JREFUeF7t2sENw0AMA8Fz53HlNpAevB9OCgihORF6JNc55zk+BAh8KXBfivalr+8m8BdQNItAIBBQtABZBAFFswMEAgFFC5BFEFA0O0AgEFC0AFkEAUWzAwQCAUULkEUQUDQ7QCAQULQAWQQBRbMDBAIBRQuQRRBQNDtAIBBQtABZBAFFswMEAgFFC5BFEFA0O0AgEFC0AFkEAUWzAwQCAUULkEUQUDQ7QCAQULQAWQQBRbMDBAIBRQuQRRBQNDtAIBBQtABZBAFFswMEAgFFC5BFEFA0O0AgEFC0AFkEAUWzAwQCAUULkEUQUDQ7QCAQULQAWQQBRbMDBAIBRQuQRRBQNDtAIBBQtABZBAFFswMEAgFFC5BFEFA0O0AgEFC0AFkEAUWzAwQCAUULkEUQUDQ7QCAQULQAWQQBRbMDBAIBRQuQRRBQNDtAIBBQtABZBAFFswMEAgFFC5BFEFA0O0AgEFC0AFkEAUWzAwQCAUULkEUQUDQ7QCAQULQAWQQBRbMDBAIBRQuQRRBQNDtAIBBQtABZBAFFswMEAgFFC5BFEFA0O0AgEFC0AFkEAUWzAwQCAUULkEUQUDQ7QCAQULQAWQQBRbMDBAKB33XOeYIgEQSWBVy05dc3eybgomXUgpYFXLTl1zd7JuCiZdSClgVctOXXN3sm4KJl1IKWBVy05dc3eyagaBm1oGUBRVt+fbNnAoqWUQtaFlC05dc3eyagaBm1oGUBRVt+fbNnAoqWUQtaFlC05dc3eybgnyEZtaBlARdt+fXNngm4aBm1oGUBF2359c2eCbhoGbWgZQEXbfn1zZ4JuGgZtaBlARdt+fXNngkoWkYtaFlA0ZZf3+yZgKJl1IKWBRRt+fXNngkoWkYtaFlA0ZZf3+yZgKJl1IKWBRRt+fXNngn4Z0hGLWhZwEVbfn2zZwIuWkYtaFnARVt+fbNnAi5aRi1oWcBFW359s2cCLlpGLWhZwEVbfn2zZwKKllELWhZQtOXXN3smoGgZtaBlAUVbfn2zZwKKllELWhZQtOXXN3sm4He0jFrQsoCLtvz6Zs8EXLSMWtCygIu2/PpmzwRctIxa0LKAi7b8+mbPBFy0jFrQsoCLtvz6Zs8EXLSMWtCywP0C6nLAcP+Cg/oAAAAASUVORK5CYII=',
};
/**@name 椭圆 **/
const ellipse = {
shape: 'circle',
img:
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAAAXNSR0IArs4c6QAABXNJREFUeF7tnY111DAQhC+VAJWEVBKoBKgEqARSCUklkHG8h85nn2X5Z0fa8Xt59xOdtbvzaSXZsn130hY6AnehvZfzJwEQHAIBIACCRyC4+8oAAiB4BIK7rwwgAIJHILj7ygACIHgEgruvDCAAgkcguPvKAAIgeASCu68MIACCRyC4+8oAAiB4BIK7rwwgAIJHILj7ygACIHgEgrvfagZ43+uKV/sbSv1u8MVL8vm5f5++2vumkKkZABP2Y6/I/Q2xtxLNIPh9Op2eEkjwucqtFgAgNoTGK4Q20VmCPgQDn6uAghUACP2pV/cLi8oL7TAI0LUABkogmAAw0Rlb+ELtR4sbED+ZYPAGwESvtZWXgkEDgwcAJvpj36eXBrGV3wEGZIUfr93e4TONIwGI2tpzQXXJCkcAAOGR4m1QlxuQyOUAw+cjxgp7AiDh1yMMEL713cP6vY3sYQ8AlOq3lwogPOwxRtgagK99ut8+BNrjLoPFrQDAkbnvGtUfQqmBgMa2etsCALX61TIU7QBjg9UQrAEAfT1aPdtx+aJoVvqj1dmgFACI/qvSoLVodnE2KAFAKZ8ToSIIlgKAVq+UzwkArFo8XVwCgMTnFT61bBEEuQBI/DrENyuzIcgBQOLXJX4KwYc50+cAkPhzEeT+PzLBTQhuAaDRPre4udZhnQHOLI5uUwBonp8b3jrKAQCAcLVNAfBHx/XrUDbTysn1BWMA4PCuFm9kRraiYliVjFPKF9sQAKX+ihQtMPWqKxgCoFF/QVQr+snVrCAFAGkf6V9b2xG4OGeQAqDW37bw5t1FFjAA1PfHEN+8xGCwu1TNANDIPxYA5xmBAfA3lv/ytj9E/AwANPiLyUPXDQiAmOLD6+4cAQBQ/x8Tgm42AAB03D8mAN0kAABoABgXgC4DCIC4ADwIgLjiw3MBEFv/t1mAuoC4FCgDxNW+81yDQAHwdpGnLveKSUJ3HEAAxBT/fChYawGCA4AbPeBwsLZYEegWiNp6AHUDscQ/LwYyALQmIBYA58vFDAB1A7EAuFoTCPfVDcSA4OIKoXRZuLJADADOrf88EEj81uqgtiG4uj5weGmYskDbAFy0/rEMgO80I2gTgtEbRYxdHq47gLYHwOStYqZuEAEIMCuwBzC2F5JYHl2lfnP/1j2CdI6gDUgmxZ8aA6Ru60ZRdUNw8wZROQCgjCCoE4LRW8IMXZm7T6CVFwR1QZAlfm4GEASNir8UAHUH/CDM9vmlXUD6O80OOEGYvBnkLXNzxwDDfeg4AQ8Eqx4yWQoA3NfzAf0hyB7sTZm6BgDbpx4Z5wNC0SNithgDjLmrbHAcBNkPg8gxaYsMkNajE0k5US8rs8tzhLcGIB0bPOpkUpnSg1+tfjbgHrOAHM+sWxAIOdG6LrOr8FbdHhlgbMqIRSYCIQ+EQ4Q/EgCrCxkBMwaAoItRnVr8XrOAPLb/l1L38BaLXR4Jv0SMI7qAW/ZYVrgP9pQSHMB5eg3M6qd/LxF7rKw3AMMpZApES92EtXQI392lm2VjAmBs8AgIkB0MDJa4zdkBwSH0S/9KJXpqPDMAc0AACoZFqxAbf0jp2NzT+hydtQIw5pcBYJkCZdLvlsRiqizEtQEb3qNVY6NL5yXO1pQBSvxLM8TUe9uvCZ1+Hn5XYgP1b1oHgDr4DMYJAAYVHG0QAI7BZ6haADCo4GiDAHAMPkPVAoBBBUcbBIBj8BmqFgAMKjjaIAAcg89QtQBgUMHRBgHgGHyGqgUAgwqONggAx+AzVC0AGFRwtEEAOAafoWoBwKCCow0CwDH4DFULAAYVHG0QAI7BZ6haADCo4GiDAHAMPkPVAoBBBUcbBIBj8BmqFgAMKjja8A/UQc8BdlckFQAAAABJRU5ErkJggg==',
};
/**@name 箭头 **/
const arrowRight = {
shape: 'triangle-forward',
img:
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAAAXNSR0IArs4c6QAABYVJREFUeF7tnd+rTVEQx8e7P9H/QRRF+fWgKA9EEYp4UBRFFA+KeFCUB6J4UMQDUR5oumt1znXPuWutvWbWzF7re17vrJlZ3/mctXcze9+zg/AZWoEdlbvfSUQ/Kn1guaECtQBcIqK7RHTFcA8IXaGABAC7iOg6Ee0honcVuWCpgQJSAHDqfwIEJwz2gZATFZAEIKbwKIDwZGJOWNZQAQ0AYvrHAggNt4NQpQpoAsC5vAkQ3CxNDPZtFNAGIO7iQgDhc5ttIUquAq0A4Hy+BQjO5iYHO30FWgIQd3MngPBSf3uIkFLAAoCY034iOpRKEH/XVcASAN7Z83Aa3NfdJryvU8AagJjXaSLaTUQ/Uaq2CngBgHf9MZwGmCs0ZMATAHHbmCsMDgBvH3OFRhB4PAGWt465gjII3gGI28dcQQmEuQDA28dcQQGCOQEQt4+5giAIcwSAt/899A0wV6iEYa4AYK5QWfi4fO4AYK5QCUIvALAML8JlAXOFAih6AgBzhYLC93YJ+H/rmCtkwtDjCbC89RvhsoD3FdYA0TsAmCskToIRAIgSYK6wAoaRAIjbPx4uC5lXyb7NRgQAc4UlpkcFAHOFoMDoAMS5Ar/ZfKbvw3717gDAQpch31cAAFu/GEO9rwAAVp+MPFfgy8K93i8LAGD7CvP7CgxCt/8HCQCkv+JdzxUAQBqAaMFzBT4N3uYv8W8JAMpq1N37CgCgDIDu5goAYBoAy3MFviz8rXNjtxoA1Gs/6/cVAEA9ALOeKwAAOQBmOVcAALIARG+zmSsAAB0Aolf3cwUAoAsAe3c9VwAA+gDECC7nCgCgHQAc6VN4HtHN/0ECAG0BcDdXAAA2AHBUF3MFAGAHQIz8OFwWTH5fAQDYA2A6VwAAfgDgTJrPFQCALwBiNhfDZUH99xUAgE8Ams0VAIBfAJrMFQCAfwBihgeI6KB0ugBAWlFdf+JzBQCgWzAt72JzBQCgVSJ9vzxX4OcRL9eEAgA16vlYu4+IDk9NBQBMVc5+3e1wAryqSQUA1Khns/ZraBKdlwgPACRUbOeDi87X/S9SIQGAlJK6fl6Hwt+SDgMApBWV98c3eHyjp/IBACqyijh9GL71T0W8rXECADTVneb7dyj8yWnLy1YBgDK9tK2vhTv8D9qBon8A0Erp7eNwwfnu/mrrdABAa8W3xjsViv/LIhUAYKH6Rsxn4bjnmz2zDwCwkb6qfy+ZMgCQVDPtS6R/nw6TbwEA8rWqseT+Pd/knatxorEWAGioutmneP9eMmUAIKnmZl9q/XvJlAGApJoLX0eIaK+Oa1mvAEBWzyb9e8mUAYCMmk379zIpb3gBAPVqNu/f16e88AAApqtp1r+fnvLWlQBgmpqm/ftpKa9eBQDK1HTRvy9LeXtrAJCvppv+fX7KaUsAkNbIXf8+nXK+BQBYr5Xb/n1+edOWAGC1Rq779+my5lsAgM1azaJ/n1/etCUAWGg0m/59uqz5FgCAaHb9+/zypi1HBmC2/ft0WfMtRgWA+/f8hM77fKn6tBwNgC7695IojgRAN/17AFCmAPfv+bh/ULZsDOveT4Au+/eSaPYKQNf9ewAweP8eAAzevwcAg/fvAcDg/XsAMHj/fmQA0L+XrP7M3gtA/164+OxuDn0A9O8VCh9degcA/XvF4ns+AdC/Vy685xMA/ftGxfd2AqB/37Dwnk6AIZ6/N6htVkjrm8Bhnr/PqoaBkRUAwz1/b1DbrJAWAAz5/H1WNQyMWgIw9PP3BrXNCtkCAPTvs0phY6QNAPr3NnXNjqoFAPr32SWwNdQAAP1725oWRZcEAP37Iul9GEsBgP69j3oWZyEBwFEiqvr92uKssUBMgVoAxBKBIxsFAICN7m6iAgA3pbBJ5B/HiF2QrT6M+QAAAABJRU5ErkJggg==',
};
const shape = {
star,
diamond,
circle,
triangleTop,
square,
rectangle,
ellipse,
arrowRight,
};
export default shape;
看看通过图片绘制的效果:
好像看着还不错吧?😊 起码形状看起来像那么一回事了。
容器大小变化,图像也不会乱掉了,只是等比例缩小而已,可以自个试试哈。
然而,你以为这就完了❓
⏰当然还没,你发现没有,当形状选择正方形和长方形的时候,这玩意变成圆形了?😬
分析了一下原因,主要还是数据量的问题,由于绘制的图片里面形状过大,数据量又不够,大概是这样子:
为啥中间有一个圆呢?因为咱们还有一个 shape 属性设置的值是 circle。
还记得 maskImage 属性的描述吗?
"它允许你提供一个图像,它会从绘图文本中排除白色区域的轮廓图像。"
原文描述:
A silhouette image which the white area will be excluded from drawing texts.
The shape option will continue to apply as the shape of the cloud to grow.
那么,如何解决这个问题呢?
简单嘛,数据量不够,加数据不就行啦?真是个聪明的小伙!😁
确实,是能解决的。其实也可以调整一下容器大小(.container)或者配置中的 width/height 属性也可以解决,然而,真就这样子❓
当然不是,💢谁能保证一定有那么多数据量或者尺寸适中呢!!!
这会,细心的你一定发现...了吧💯,如果我们能将上面中间的圆形也变成正方形是不是就可以了呢❓
可惜的是 shape 属性仅支持circle/cardioid/diamond...就是没有正方形和长方形,咋整?
不怕,shape 属性还支持回调函数(callback function)形式,这个特性可以让咱们自定义各种所需的形状。但这需要你有较好的数学和算法能力,反正小编我是没有,俺只能从网上找现成的捡过来用。🙊
关于如何创建形状的计算公式,你可以先从 echarts-wordcloud源码 中模仿。
其中数学计算可以用这个网站辅助:传送门。
而 shape 属性的回调函数形式要如何使用?才能让其支持正方形呢?其实上面已经写过了,可以看看 shape.js 文件,里面每个形状对象(看正方形的对象)还有另外一个属性,就是为此准备的。
setOptions() {
...
const shapeConfig = shape[this.shape];
// 让shape属性形状也和提供的图像形状对应上,避免少量数据时出现的异常
seriesItem.shape = shapeConfig.shape;
const maskImage = new Image();
...
}
看效果:
即使只有少量的数据也能保持图像的形状,这就很棒了!😀
好,到这里,词云图的形状功能相信你已经能得心应手,任何形状都不在话下了,咱们就继续其他功能。🏃
颜色设置
搞定了形状,接下来令人期待的功能肯定就是颜色啦🌈,现在的词云图全是单一的蓝色,显得有些单调,花里胡哨快安排起来。😉
词云图的颜色配置可以分为两种方式:全局设置和单个词语的设置。
全局随机颜色:
_options: {
series: [
{
...,
// 全局样式
textStyle: {
// 固定一种颜色
// color: 'red',
// 随机颜色
color: function () {
return 'rgb(' + [
Math.round(Math.random() * 160),
Math.round(Math.random() * 160),
Math.round(Math.random() * 160)
].join(',') + ')';
}
},
},
],
},
单个设置:
{ name: "深圳", value: 164910, textStyle: { color: 'red' } },
而咱们需要完成的效果如下:
配色规则大致是这样子的:设定几个主题,每个主题下有若干个颜色,然后通过计算每项数据的 name 属性的哈希编码,再将其与主题下的颜色对应。
产生的效果就是在同一个主题下,某项数据{name: '橙某人'}对应的颜色永远会是某一个颜色,不会改变。
具体实现:
// utils.js
/**
* @name 通过字符串的hash得到对应的颜色
* @param { string } str: 目标字符串
* @param { string[] } colors: 颜色模版
* @returns { Array<string> }
*/
export function getStringColor(str, colors = []) {
if (!str) return colors[0];
if (!colors || colors.length === 0) return;
return colors[getBKDRHASH(str) % colors.length];
}
/**
* @name 字符串hash
* @param { string } str: 目标字符串
* @returns { number }
* @description BKDRHASH是一种字符哈希算法,可以自行查阅资料
*/
export function getBKDRHASH(str) {
const seed = 131;
let hash = 0;
let charCode = 0;
let index = 0;
while ((charCode = str.charCodeAt(index))) {
hash = (hash * seed + charCode) % Number.MAX_SAFE_INTEGER; // 求余来防止溢出
index++;
}
return hash;
}
<script>
...
import { getStringColor } from './utils';
export default {
data() {
return {
...,
themeValue: '1'
}
},
computed: {
...,
themeOptions() {
return [
{
name: '姹紫嫣红', value: '1', color: ['#02E1FD','#7F96FD','#02C0FF','#FF0270','#FFA621','#FEE600','#27F28E','#96F62A','#F98639','#28D5D7','#F4F452','#768EFF'],
},
{
name: '馥郁芬芳', value: '2', color: ['#07EDE9','#FF7D6C','#FFDD71','#81FFC3','#E3A3FC','#F8FFA3','#9286FE','#9AEE8C','#F4F452','#02C0FD','#B598FF','#738CFF'],
},
{
name: '蔚蓝海岸', value: '3', color: ['#94E5FA', '#69CCF0','#9AF1E8','#4AC5DE','#5AA9FF','#4EAFF4','#5BE4C5','#43BBD9','#37CAFF','#70E2FF','#4096F3','#719FFC'],
},
]
}
},
methods: {
...,
setOptions() {
...
seriesItem.data = data.map(item => ({
...item,
textStyle: {
color: getStringColor(item.name, theme.color)
}
}));
...
}
},
}
</script>
这下就足够花里胡哨了吧,产品经理看了都说好。
排列方式
接下来要讲的是词云图的排列方式,也就是"文本"的旋转角度问题。
观察上面展示过的词云图,文本的旋转角度📐基本都是-90度、-45度、0度、45度、90度。
这是因为咱们设置了 rotationRange 属性与 rotationStep 属性。
// 文字旋转角度范围
rotationRange: [-90, 90],
// 步长, 在[-90, 90]范围内随机旋转,-90/-45/0/45/90
rotationStep: 45,
而咱们要来做一个如下功能:
具体实现:
<script>
...
/** @name 排列方式 **/
const SORT = {
horizontal: {
rotationRange: [0, 0],
rotationStep: 0,
},
diagonal: {
rotationRange: [-90, 90],
rotationStep: 7,
},
blendHV: {
rotationRange: [0, 90],
rotationStep: 90,
},
blendHC: {
rotationRange: [0, 90],
rotationStep: 45,
},
};
export default {
data() {
return {
...,
sortValue: 'horizontal'
}
},
computed() {
sortOptions() {
return [
{ label: '横向', value: 'horizontal' },
{ label: '对角线', value: 'diagonal' },
{ label: '横竖混排', value: 'blendHV' },
{ label: '横切混排', value: 'blendHC' },
];
}
},
methods: {
setOptions() {
...,
// 排列方式
const sortConfig = SORT[this.sortValue];
if (sortConfig) {
seriesItem.rotationRange = sortConfig.rotationRange;
seriesItem.rotationStep = sortConfig.rotationStep;
}
...
}
}
}
</script>
应该不是很难吧,很好理解的啦。😀 😀 😀
- 横向:所有文本都不旋转。
- 对角线:理想下是所有文本应该是旋转-45度、45度、135度、-135度,但是好像无法整出来😵。换了一个想法,只要不产生横和竖的角度就行,所以让文本都按7度的步长去随机,这样出来的效果好像也还行。🙈
- 横竖混排:所有文本都不旋转或者旋转90度。
- 横切混排:所有文本都不旋转或者旋转45度。
🔉产品经理小要求:文本不要倒着展示。
![]()
字体设置
😀 讲完了比较复杂的功能,接下来就是一些辅助性的小功能了。
比如我们可以设置字体的大小范围、字体类型等。
<script>
export default {
data() {
return {
...,
fontRange: {
min: 12,
max: 24,
},
fontFamilyValue: '微软雅黑'
}
},
computed() {
fontFamilyOptions() {
return [
'Arial',
'Courier New',
'Georgia',
'Helvetica',
'Impact',
'times new roman',
'Trebuchet ms',
'Verdana',
'仿宋',
'华文仿宋',
'华文宋体',
'华文楷体',
'宋体',
'微软雅黑',
'黑体',
'楷体',
'方正楷体',
'方正黑体',
'方正仿宋',
].map(item => ({ label: item, value: item }))
}
},
methods: {
setOptions() {
...,
// 字号范围
seriesItem.sizeRange = [
this.widget.fontRange.min,
this.widget.fontRange.max,
];
// 字体设置
const fontFamily = this.widget.fontFamily;
if (fontFamily) {
seriesItem.textStyle.fontFamily = fontFamily;
}
...
}
}
}
</script>
tooltip
_options: {
tooltip: {
show: true,
},
...
}
图片下载
/** @name 导出图片 **/
downloadPicture(name) {
const base64 = this._chart?.getDataURL({
type: 'png',
pixelRatio: 1.5,
backgroundColor: '#fff',
});
const fileName = name + '_' + new Date().getTime();
const link = document.createElement('a');
link.download = fileName;
link.style.display = 'none';
link.href = base64;
document.body.appendChild(link);
link.click();
URL.revokeObjectURL(link.href);
document.body.removeChild(link);
}
点击事件
/** @name 初始化图表 **/
initChart() {
this.$nextTick(() => {
if (this._chart) this._chart.dispose();
if (this.$refs?.container) {
this._chart = echarts.init(this.$refs.container);
}
if (!this._chart) return;
// 尺寸自适应
addListener(this.$refs.container, this.resizeHandler);
// 事件绑定
this._chart.on(
'click',
throttle(params => this.handleClick(params), 350, {
leading: true,
trailing: false,
}),
);
this._chart.clear();
this.setOptions();
});
}
完整源码
传送门 👈👈👈
至此,本篇文章就写完啦,撒花撒花。
希望本文对你有所帮助,如有任何疑问,期待你的留言哦。
老样子,点赞+评论=你会了,收藏=你精通了。