d3js -- 词云(word cloud)

  词云也叫标签云,是文本数据的可视化展示,通常根据字体颜色和大小表示每个标签的重要性。d3并没有词云模块,因此需要独立导入d3-cloud这个模块。

  词云用到的数据形式是一组数组对象。通常,默认使用text表示显示标签,value用来计算字体大小。用户也可以使用自定义的名称,这时候需要改变函数。

  下面是一个制作词云的事例。首先先看看词云的效果, 其中archimedean和rectangular为单词的螺旋类型,也可以自定义其他形式。此文只展示这两种。

图一、阿基米德螺线式词云

图二、rectangular式词云

  一、html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>词云图</title>
    <script src="../../../d3.min.js"></script>
    <!-- 专门绘制词云的包 -->
    <script src="../d3.layout.cloud.js"></script>
</head>
<body>
    <div id="selectButton"></div>
    <div id="word_cloud"></div>
    <script src="./index.js" type="module"></script>
</body>
</html>

  二、js文件

  步骤一、前置准备

// 1、create dimensions
const dms = {
    width: 1000,
    height: 550,
    margin: {
        top: 50,
        left: 50,
        bottom: 50,
        right: 50
    }
}
dms.innerWidth = dms.width - dms.margin.left - dms.margin.right;
dms.innerHeight = dms.height - dms.margin.top - dms.margin.bottom;

const svg = d3.select('#word_cloud')
    .append('svg')
    .attr('width', dms.width)
    .attr('height', dms.height);

const maingroup = svg.append('g')
    .attr('transform', `translate(${dms.margin.left}, ${dms.margin.top})`);
    

const wordCloundArea = maingroup.append('g')
    .attr('class', 'word-cloud-area');

// 设置颜色
const colors = d3.scaleOrdinal(d3.schemeCategory10);

// 设置data和单词螺旋类型
let data, spiralValue = 'archimedean';

 步骤二、读取文件

  这里直接准备txt文件,里面存放需要的中文或者英文篇章。

// 文本文件路径
const path = '../data/word.txt';
// 读取文件
d3.text(path).then(loadData => {
    // 处理数据,将数据转换成指定格式的数据
   data = handleRequestData(loadData);
   //console.log(newData);
   renderWord();

})

  handleRequestData是用来获取所需数据对象的方法,可将其处理成下面这种形式,也就是第二段落所述的用户自定义的名称:

[{
   text: "Life",
   fontSize: 0.9999 
},
......
]

  这里这个函数不做多介绍,根据自身需要来处理,大致过程就是

    1、正则处理,去除不需要的符号或其他元素,比如, ; :等

    2、计算每个单词出现的次数,并分配字体大小

    3、转换格式,即转换成上述格式。

  另外,直接使用上述格式,更方便,就不需要做1,2两步的处理了

 步骤三、renderWord()函数

function renderWord() {
    // add button
    const button = d3.select('#selectButton');
    button.call(changeValueButton, {
        value: ['archimedean', 'rectangular'],
        onButtonClicked: onButtonSelectionClicked
    });
    let transition = d3.transition().duration(2000).ease(d3.easeLinear);
  // 布局
    const layout = d3.layout.cloud()
        .size([dms.innerWidth, dms.innerHeight])
        .words(data)
        .font('Impact')
        .spiral(spiralValue) // archimedean, rectangular
        .fontSize(d=>d.fontSize * 12) // 如果不是默认的数据,需要自定义哪个属性来应用,比如fontSize
        .on('end', draw);
    // 执行layout算法
    layout.start();
    // 执行完layout算法后,会返回一个新数据。

    function draw(words) {
        // console.log(words, layout.size());
        const wordCloud = wordCloundArea
            .attr('transform', `translate(${layout.size()[0] / 2}, ${layout.size()[1] / 2})`);
            
        const wordCloudG = wordCloud.selectAll('text')
            .data(words);
        const wordCloudGEnter = wordCloudG
            .enter().append('text')
            .text(d=>d.text)
            .attr('text-anchor', 'middle')
            .style('font-size', d=>d.size)
            .style('font-family', d=>d.font)
            .style('fill', (d, i)=>colors(i%10))
            .merge(wordCloudG)
            .transition(transition)
            .attr('transform', d=>`translate(${d.x}, ${d.y})rotate(${d.rotate})`);

    }
}

  上述通过d3.layout.cloud()创建了布局对象,size设置了词云的大小,words为词云数据,font为设置的字体,spiral为单词螺旋模式 ,fontSize为字体大小,on方法定义了draw函数,用来在布局完成后去执行。layout.start(),用来启动布局算法。

  draw()函数里进行了绘图,呈现了上面的效果。

 步骤四、定义按钮。

// 定义按钮
export const changeValueButton = (selection, options) => {
    let { value, onButtonClicked } = options;
    // selectButton
    let button = selection.selectAll('button')
        .data(value);
    // button.exit().remove()
    button = button
        .enter()
        .append('button')
        .merge(button)
        .attr('id', value)
        .attr('value', d=>d)
        // .style('color', '#fff')
        .style('background', d=>d===spiralValue ? '#00bcd4' : '')
        .text(d=>d)
        .on('click', function() {
            // console.log('tttt', this.value)
            onButtonClicked(this.value);
        })
        
}

 步骤五、获取点击的按钮

const onButtonSelectionClicked = radio => {
    spiralValue = radio;
    renderWord()
}

  到这里词云绘制完成。

posted @ 2022-11-06 15:40  先起这个昵称  阅读(2470)  评论(0编辑  收藏  举报