软件工程应用与实践——词云图的呈现

Posted 叶卡捷琳堡

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了软件工程应用与实践——词云图的呈现相关的知识,希望对你有一定的参考价值。

2021SC@SDUSC

一、功能概述

在老年健康管理系统中,首页词云图是一个独特的功能。经过小组成员交流讨论,决定由我负责词云图代码的分析。词云图中词语来自健康知识word文档中的分词。分词的功能与停用词的去除在下一篇博客中会提到,本篇博客先关注最基本的部分,即前端词云图的获取与呈现。

二、前端代码

2.1 echarts配置

本项目中使用echarts的echarts-wordcloud库实现词云图。在使用前需要先在vue项目中下载和配置echarts

安装依赖

npm install echarts
npm install echarts-wordcloud

在main.js中引入echarts

本项目通过Vue.prototype.$echarts定义了echarts全局变量

import * as echarts from 'echarts';
Vue.prototype.$echarts = echarts

2.2 echarts使用

定义一个固定大小的div用于呈现词云图

<div ref="wordcloud" class="wordCloudCharts"></div>

用js方法从后端获取数据

这里使用async和await,实现串行执行代码。只有当then方法中的代码执行完毕后,才会调用initWordCloud方法,用于生成词云图

 async mounted() {
   //发送axios请求,从后端获取词云数据
   await instance.get('wordCloud').then(res=>{
     this.wordList = res.data
   })
   this.initWordCloud();
 }

词云图数据的格式

echarts的wordcloud库要求使用name和value的对象用于表示词的名字和词所占的比例

data(){
  return{
    //词云数据
    wordList:[
		{name:'xxx',value:0}
	],
  }
},

initWordCloud方法

首先调用init方法,传入对应的dom对象,获取echarts对象。之后通过setOption方法指定type为wordCloud,并设置相关属性。

需要注意的是,由于词云图的字体颜色有很多种,因此这里使用Math.round(Math.random() * 255),对0-255中获取的随机值进行四舍五入后确定颜色值

此外,本项目设置词云中词的旋转方向为水平方向,方便用户阅读。

initWordCloud(){
  let myChart = this.$echarts.init(this.$refs.wordcloud);
  myChart.setOption({
    series: [
      {
        type: "wordCloud",
        //词之间的距离
        gridSize: 10,
        //字的大小范围
        sizeRange: [14, 60],
        //词的旋转方向,[0,0]表示水平方向
        rotationRange: [0, 0],
        //字体颜色
        textStyle: {
          color: function() {
            return (
              "rgb(" +
              Math.round(Math.random() * 255) +
              ", " +
              Math.round(Math.random() * 255) +
              ", " +
              Math.round(Math.random() * 255) +
              ")"
            );
          }
        },
        //位置相关设置
        left: "center",
        top: "center",
        right: null,
        bottom: null,
        width: "200%",
        height: "200%",
        //数据
        data: this.wordList
      }
    ]
  })
}

三、echarts源码分析

上面简单介绍了本项目如何使用echarts构建词云图,为了更深入的理解echarts-wordcloud如何实现词云图,下面对echarts-wordcloud的源码进行分析

echarts-wordcloud的github地址:https://github.com/ecomfe/echarts-wordcloud

echarts-wordcloud.js

在echarts-wordcloud.js文件中,extendSeriesModel()方法用于获取和保存词云的基本属性。

  • optionUpdated函数获取用户设置的词云图属性,其中gridSize(词与词之间的距离),最小值为4。也就意味着,如果用户设置词与词之间的距离小于4,将会失效。
  • defaultOption中保存了词云图的基本属性,如果用户没有进行自定义,则会直接使用默认配置
external_echarts_.extendSeriesModel({
    type: 'series.wordCloud',
    visualStyleAccessPath: 'textStyle',
    visualStyleMapper: function (model) {
        return {
            fill: model.get('color')
        };
    },
    visualDrawType: 'fill',
    optionUpdated: function () {
        var option = this.option;
        option.gridSize = Math.max(Math.floor(option.gridSize), 4);
    },
    getInitialData: function (option, ecModel) {
        var dimensions = external_echarts_.helper.createDimensions(option.data, {
            coordDimensions: ['value']
        });
        var list = new external_echarts_.List(dimensions, this);
        list.initData(option.data);
        return list;
    },
    defaultOption: {
        maskImage: null,
        // Shape can be 'circle', 'cardioid', 'diamond', 'triangle-forward', 'triangle', 'pentagon', 'star'
        shape: 'circle',
        left: 'center',
        top: 'center',
        width: '70%',
        height: '80%',
        sizeRange: [12, 60],
        rotationRange: [-90, 90],
        rotationStep: 45,
        gridSize: 8,
        drawOutOfBound: false,
        textStyle: {
            fontWeight: 'normal'
        }
    }
});

在extendChartView方法中,定义了remove和dispose方法,并且在ondraw方法中绘制对应的图像

  • 首先调用removeAll()方法清空所有之前的元素
  • 通过seriesModel.getData()方法获取用户在使用时传入的数据
  • 通过seriesModel.get(‘gridSize’)方法获取用户传入的词距
  • textEl变量保存文字的样式,包括x轴与y轴的位置
  • remove方法调用removeAll()方法和dispose()方法去除原有的数据并释放实例
  • dispose方法调用this.model.layoutInstance.dispose()方法释放echarts实例
external_echarts_.extendChartView({
    type: 'wordCloud',
    render: function (seriesModel, ecModel, api) {
        var group = this.group;
        group.removeAll();
        var data = seriesModel.getData();
        var gridSize = seriesModel.get('gridSize');
        seriesModel.layoutInstance.ondraw = function (text, size, dataIdx, drawn) {
            var itemModel = data.getItemModel(dataIdx);
            var textStyleModel = itemModel.getModel('textStyle');
            var textEl = new external_echarts_.graphic.Text({
                style: external_echarts_.helper.createTextStyle(textStyleModel),
                scaleX: 1 / drawn.info.mu,
                scaleY: 1 / drawn.info.mu,
                x: (drawn.gx + drawn.info.gw / 2) * gridSize,
                y: (drawn.gy + drawn.info.gh / 2) * gridSize,
                rotation: drawn.rot
            });
            textEl.setStyle({
                x: drawn.info.fillTextOffsetX,
                y: drawn.info.fillTextOffsetY + size * 0.5,
                text: text,
                verticalAlign: 'middle',
                fill: data.getItemVisual(dataIdx, 'style').fill,
                fontSize: size
            });
            group.add(textEl);
            data.setItemGraphicEl(dataIdx, textEl);
            textEl.ensureState('emphasis').style = external_echarts_.helper.createTextStyle(itemModel.getModel(['emphasis', 'textStyle']), {
                state: 'emphasis'
            });
            textEl.ensureState('blur').style = external_echarts_.helper.createTextStyle(itemModel.getModel(['blur', 'textStyle']), {
                state: 'blur'
            });
            external_echarts_.helper.enableHoverEmphasis(
                textEl,
                itemModel.get(['emphasis', 'focus']),
                itemModel.get(['emphasis', 'blurScope'])
            );
            textEl.stateTransition = {
                duration: seriesModel.get('animation') ? seriesModel.get(['stateAnimation', 'duration']) : 0,
                easing: seriesModel.get(['stateAnimation', 'easing'])
            };
            textEl.__highDownDispatcher = true;
        };
        this._model = seriesModel;
    },
    remove: function () {
        this.group.removeAll();
        this._model.layoutInstance.dispose();
    },
    dispose: function () {
        this._model.layoutInstance.dispose();
    }
});

四、总结

本篇博客就项目中如何使用echarts实现词云图,数据的格式,echarts-wordcloud模块部分关键代码进行了剖析。除了这一部分之外,词云获取,筛选的过程,后端的具体代码在之后的博客中还会继续补充。

以上是关于软件工程应用与实践——词云图的呈现的主要内容,如果未能解决你的问题,请参考以下文章

软件工程应用与实践——词云的获取

生成中文词云图的制作:带有不同的背板

云图说|ROMA演进史:一个ROMA与应用之间不得不说的故事

百度脑图可以做词云图

R语言画词云图——建模常用软件

R语言画词云图——建模常用软件