上一篇: 雷达图 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
树图类的数据不再是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}
]
}
]
}
]
}
导入数据
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));
});
}