D3 二维图表的绘制系列(十六)矩形树状图

上一篇: 雷达图 https://blog.csdn.net/zjw_python/article/details/98486655

下一篇: 树图 https://blog.csdn.net/zjw_python/article/details/98492510

代码结构和初始化画布的Chart对象介绍,请先看 https://blog.csdn.net/zjw_python/article/details/98182540

本图完整的源码地址: https://github.com/zjw666/D3_demo/tree/master/src/treeMapChart/basicTreeMap

1 图表效果

在这里插入图片描述

2 数据

树图类的数据不再是csv格式,而是json

{
    "name": "grandfather",
    "children": [
        {
            "name": "father",
            "children": [
                {
                    "name": "son",
                    "children": [
                        {"name": "grandson1", "house": 2},
                        {"name": "grandson2", "house": 3},
                        {"name": "grandson3", "house": 4}

                    ]
                }
            ]
        },
        {
            "name": "mother1",
            "children": [
                {
                    "name": "daughter1",
                    "children": [
                        {"name": "granddaughter1", "house": 4},
                        {"name": "granddaughter2", "house": 2}
                    ]
                },
                {
                    "name": "daughter2",
                    "children": [
                        {"name": "granddaughter3", "house": 4}
                    ]
                }
            ]
        },
        {
            "name": "mother2",
            "children": [
                {
                    "name": "son1",
                    "children": [
                        {"name": "grandson4", "house": 6},
                        {"name": "granddaughter4", "house": 1}
                    ]
                },
                {
                    
                    "name": "son2",
                    "children": [
                        {"name": "granddaughter5", "house": 2},
                        {"name": "grandson5", "house": 3},
                        {"name": "granddaughter5", "house": 2}
                    ]
                    
                }
            ]
        }

    ]
}

3 关键代码

导入数据

d3.json('./data.json').then(function(data){
....

一些样式配置参数

const config = {
        margins: {top: 80, left: 80, bottom: 50, right: 80},
        textColor: 'black',
        title: '矩形树图',
        hoverColor: 'white',
        animateDuration: 1000
    }

数据转换,树图是层次型的数据结构,首选使用d3.hierarchy构造节点,接着将生成root节点传入d3.treemap布局函数中,返回具有布局信息的节点,每个节点都具有x0,x1,y0,y1

/* ----------------------------数据转换------------------------  */
    const root = d3.hierarchy(data)
                    .sum((d) => d.house)
                    .sort((a,b) => a.value - b.value);

    const generateTreeMap = d3.treemap()
                    .size([chart.getBodyWidth(), chart.getBodyHeight()])
                    .round(true)
                    .padding(1);
    
    generateTreeMap(root);

直接绑定具有布局信息的节点数组,然后运用渲染矩形,非常简单

/* ----------------------------渲染矩形------------------------  */
    chart.renderRect = function(){
        const cells = chart.body().selectAll('.cell')
                                    .data(root.leaves());
                
              cells.enter()
                     .append('g')
                     .attr('class', (d, i) => 'cell cell-' + i)
                     .append('rect')
                   .merge(cells)
                     .attr('x', (d) => d.x0)
                     .attr('y', (d) => d.y0)
                     .attr('width', (d) => d.x1 - d.x0)
                     .attr('height', (d) => d.y1 - d.y0)
                     .attr('fill', (d,i) => chart._colors(i % 10));
            
              cells.exit()
                    .remove();     
    }

渲染文本标签,注意限制文本的长度不要超过矩形的宽度

/* ----------------------------渲染文本标签------------------------  */
    chart.renderText = function(){

        const texts = d3.selectAll('.cell')
                            .append('text');
              texts
                .attr('class', 'cell-text')
                .attr('transform', (d) => 'translate(' + (d.x0+d.x1)/2 + ',' + (d.y0+d.y1)/2 + ')' )
                .text((d) => d.data.name)
                .attr('stroke', config.textColor)
                .attr('fill', config.textColor)
                .attr('text-anchor', 'middle')
                .text( function(d){
                    if (textWidthIsOk(d, this)){
                        return d.data.name;
                    }else{
                        return '...';
                    }
                })
        
        // 检测文本长度是否合适
        function textWidthIsOk(d, text){
            const textWidth = text.getBBox().width;
            if ((d.x1-d.x0) >= textWidth) return true;
            return false;
        }

    }

最后绑定鼠标交互事件,鼠标悬停时矩形变色

/* ----------------------------绑定鼠标交互事件------------------------  */
    chart.addMouseOn = function(){

        d3.selectAll('.cell rect')
            .on('mouseover', function(){
                const e = d3.event;
                e.target.style.cursor = 'hand'

                d3.select(e.target)
                    .attr('fill', config.hoverColor);
                
            })
            .on('mouseleave', function(d,i){
                const e = d3.event;
                
                d3.select(e.target)
                    .attr('fill', chart._colors(i % 10));
            });
    }

大功告成!!!

发布了250 篇原创文章 · 获赞 88 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/zjw_python/article/details/98489369