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));
            });
    }

大功告成!!!


如果觉得这篇文章帮助了您,请打赏一个小红包鼓励作者继续创作哦!!!

在这里插入图片描述

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
D3树状图异步按需加载数据可以通过以下步骤实现: 1. 定义根节点,根节点是整个树结构的入口。 2. 定义一个函数,用于异步加载子节点的数据。这个函数需要接收一个节点作为参数,然后返回一个Promise对象,用于异步加载子节点的数据。 3. 定义一个函数来更新树状图。这个函数需要接收一个根节点作为参数,并且需要使用根节点的数据来绘制树状图。 4. 当用户点击节点时,调用异步加载子节点数据的函数,并在Promise对象被解决之后,更新树状图。 下面是一个示例代码: ``` // 定义根节点 const root = d3.hierarchy(data); // 定义异步加载子节点的函数 const loadChildren = async (node) => { const childrenData = await fetch(`http://example.com/api/children?node=${node.id}`); return childrenData.map(childData => d3.hierarchy(childData)); }; // 定义更新树状图的函数 const update = (root) => { // 绘制树状图的代码 }; // 当用户点击节点时,调用异步加载子节点数据的函数,并在Promise对象被解决之后,更新树状图 d3.select('svg') .on('click', (event, d) => { if (d.children) { d.children = null; } else { loadChildren(d).then(children => { d.children = children; update(root); }); } }); ``` 在这个示例代码中,当用户点击节点时,会调用`loadChildren`函数异步加载子节点数据。在Promise对象被解决之后,会更新树状图。注意,`loadChildren`函数返回的数据需要先转换为`d3.hierarchy`对象,才能作为子节点添加到树状图中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值