D3 二维图表的绘制系列(十九)封闭图

本文详细介绍如何使用D3.js创建封闭图,包括数据准备、样式配置、数据转换、圆圈渲染及文本显示,并实现鼠标交互效果。

上一篇: 漏斗图 https://blog.youkuaiyun.com/zjw_python/article/details/98497967

下一篇: 河流图 https://blog.youkuaiyun.com/zjw_python/article/details/98592543

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

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

1 图表效果

在这里插入图片描述

2 数据

{
    "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.pack添加布局信息

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

    const pack = d3.pack()
                    .size([chart.getBodyWidth(), chart.getBodyHeight()])
    
    pack(root);

有了布局信息之后,我们直接就用circle元素渲染一个个圆圈,非常简单

/* ----------------------------渲染圆圈------------------------  */
    chart.renderCircle = function(){
        const groups = chart.body().selectAll('.g')
                                    .data(root.descendants());
                
              groups.enter()
                      .append('g')
                      .attr('class', (d, i) => 'g g-' + i)
                      .append('circle')
                      .attr('class', 'circle')
                    .merge(groups.selectAll('.circle'))
                      .attr('cx', (d) => d.x)
                      .attr('cy', (d) => d.y)
                      .attr('r', (d) => d.r)
                      .attr('fill', (d) => chart._colors(d.depth % 10));
            
              groups.exit()
                      .selectAll('.circle')
                      .transition().duration(config.animateDuration)
                      .attr('r', 0)
                      .remove();     
    }

渲染文本,注意文本长度不要超过圆圈的直径

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

        const texts = chart.body().selectAll('.text')
                                    .data(root.descendants());

              texts.enter()
                      .append('text')
                      .attr('class', 'text')
                   .merge(texts)
                      .attr('transform', (d) => 'translate(' + d.x + ',' + d.y + ')' )
                      .text((d) => d.data.name)
                      .attr('stroke', config.textColor)
                      .attr('fill', config.textColor)
                      .attr('text-anchor', 'middle')
                      .text( function(d){
                          if (d.children) return;
                          if (textWidthIsOk(d, this)){
                              return d.data.name;
                          }else{
                              return d.data.name.slice(0,3);
                          }
                        })
        
        // 检测文本长度是否合适
        function textWidthIsOk(d, text){
            const textWidth = text.getBBox().width;
            if (d.r*2 >= textWidth) return true;
            return false;
        }

    }

最后绑定鼠标交互事件,悬停鼠标圆圈变色

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

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

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

大功告成!!!


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

在这里插入图片描述

 你手头有一些数据,想做成漂亮的放到网站上?好主意,通过浏览器来跨平台实现数据可视化是正确的选择。什么,你还想让能够响应用户操作?没问题,交互式比静态片更能吸引人去探究本源。好啦,要生成通过浏览器展示的动态,目前热门的Web数据可视化库——D3。   《灵程序设计丛书·数据可视化实战:使用D3设计交互式》这本书很有意思,而且对读者要求不高。不需要知道什么是数据可视化,也不用有太多Web开发背景就能看懂它。不信?翻一翻就知道这是一本既好玩又实用的动手指南啦!看完这本书你会怎么样呢?   掌握必要的HTML、CSS、JavaScript和SVG基础知识;   学会基于数据在网页里生成元素和为它们设置样式的技巧;   能够生成条形、散点、饼、堆叠条形和力导向;   使用平滑的过渡动画来展示数据的变化;   赋予动态交互能力,响应用户从不同角度探索数据的请求;   收集数据和创建自定义的地;   另外,《灵程序设计丛书·数据可视化实战:使用D3设计交互式》100多个代码示例都可以在线浏览! 【电子版来自互联网,仅供预览及学习交流 使用,不可用于商业用途,如有版权问题,请联系删除,支持正版,喜欢的 请购买正版书籍: https://e.jd.com/30336473.html】
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值