如何解决D3 V4条向下钻取-当x值为0时x轴刻度值重叠问题
在这里,我正在使用d3 v4 bar drill-down chart的示例。在该示例中,它使用“ size”属性来构建向下钻取,但是我使用了它的children.length。向下钻取也相应地起作用,但是当子代长度小于10时,x轴刻度值显示为十进制值。为了避免x轴刻度的十进制值,我使用了以下代码:
var xAxis = d3.axisTop()
.scale(x)
.tickFormat(d3.format("d"))
.tickValues([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]);
但是使用上述代码后,当出现0值时,x轴刻度值将重叠,如下面的屏幕截图所示。
如何避免重叠的问题
var overallJson = {
"name": "sisoc","children": [{
"organisation_id": "4","name": "orgname4","children": []
},{
"organisation_id": "5","name": "org5","children": [{
"aptcomplex_id": "4","name": "apt43","children": [{
"building_id": "3","name": "bldg3","children": [{
"floor_id": "flr_07","name": "flr_07","children": []
}]
},{
"building_id": "blg_10","name": "bld_10","children": [{
"floor_id": "5","name": "5_floor","children": []
},{
"floor_id": "flr_0700","name": "flr_0700","children": [{
"unit_id": 4,"name": "testunit","user_id": 48,"username": "test111_test","children": [{
"device_id": "test12","name": "TestMeter_2","serial": "1200000023C0123C"
},{
"device_id": "TestMeter_1","name": "TestMeter1","serial": "100000012C120202"
}]
}]
},{
"floor_id": "flr_09","name": "flr_09","children": [{
"unit_id": 1,"name": "demouser_unit_10","user_id": 36,"username": "demouser","children": [{
"device_id": "demo-meter-vc","name": "Demo Meter","serial": "10000000C9640011"
}]
},{
"unit_id": 3,"name": "unit_50","user_id": 37,"username": "stagingtest","children": []
}]
},{
"floor_id": "testfloor_!4","name": "testfloor_!4_up","children": []
}]
}]
}]
},{
"organisation_id": "6","name": "org6",{
"organisation_id": "7","name": "org7","children": [{
"aptcomplex_id": "3","name": "apt3_update","children": [{
"building_id": "1","name": "bldg1_update","children": []
}]
}]
},{
"organisation_id": "8","name": "org8_0","children": [{
"aptcomplex_id": "APT_67","name": "Amritam","children": []
}]
},{
"organisation_id": "org_109","name": "org_109","children": []
}]
};
var margin = {
top: 30,right: 120,bottom: 0,left: 120
},width = 960 - margin.left - margin.right,height = 500 - margin.top - margin.bottom;
var x = d3.scaleLinear()
.range([0,width]);
var barHeight = 20;
//var color = d3.scaleOrdinal()
//.range(["steelblue","#ccc"]);
var color = d3.scaleOrdinal(d3.schemeCategory20)
var duration = 750,delay = 25;
var partition = d3.partition();
var tooltip = d3.select("body").append("div").attr("class","toolTip");
var xAxis = d3.axisTop()
.scale(x)
.tickFormat(d3.format("d"))
.tickValues([0,20]);
var svg = d3.select("#barchartContainer").append("svg")
.attr("width",width + margin.left + margin.right)
.attr("height",height + margin.top + margin.bottom)
.append("g")
.attr("transform","translate(" + margin.left + "," + margin.top + ")");
svg.append("rect")
.attr("class","background")
.attr("width",width)
.attr("height",height)
.on("click",up);
svg.append("g")
.attr("class","x axis");
svg.append("g")
.attr("class","y axis")
.append("line")
.attr("y1","100%");
var chart_title = svg.append("text")
.attr("x",(width / 2))
.attr("y",0 - (margin.top / 2))
.attr("id","chart_title")
.attr("text-anchor","middle")
.style("font-size","16px")
.style("margin-bottom","50px")
.style("text-decoration","underline")
.text("Organisation Level");
d3.json("https://gist.githubusercontent.com/gallowayevan/f87b0911dcde85a5ccd3499a36e328e9/raw/a99e2ac89cff8255e3ae1f33f35ca01783c91139/readme.json",function(error,root) {
root = overallJson;
if (error) throw error;
root = d3.hierarchy(root)
.sum(d => d.size)
.sort((a,b) => b.value - a.value);
partition(root);
x.domain([0,root.value,function(d) {
console.log(d.data)
return 0;
}]).nice();
down(root,0);
chart_title.text("Organisation Level")
});
function down(d,i) {
if (!d.children || this.__transition__) return;
var end = duration + d.children.length * delay;
// Mark any currently-displayed bars as exiting.
var exit = svg.selectAll(".enter")
.attr("class","exit");
// Entering nodes immediately obscure the clicked-on bar,so hide it.
exit.selectAll("rect").filter(function(p) {
return p === d;
})
.style("fill-opacity",1e-6);
// Enter the new bars for the clicked-on data.
// Per above,entering bars are immediately visible.
var enter = bar(d)
.attr("transform",stack(i))
.style("opacity",1);
// Have the text fade-in,even though the bars are visible.
// Color the bars as parents; they will fade to children if appropriate.
enter.select("text").style("fill-opacity",1e-6);
//enter.select("rect").style("fill",color(true));
enter.select("rect").attr("fill",function(d,i) {
return color(i);
})
// Update the x-scale domain.
x.domain([0,d3.max(d.children,function(d) {
//console.log(d.data);
if (d.data.organisation_id) {
chart_title.text("Organisation Level")
}
if (d.data.aptcomplex_id) {
chart_title.text("Apartment Level")
} else if (d.data.building_id) {
chart_title.text("Building Level")
} else if (d.data.floor_id) {
chart_title.text("Floor Level")
} else if (d.data.unit_id) {
chart_title.text("Unit Level")
} else if (d.data.device_id) {
chart_title.text("Device Level")
}
if (d.height != 0) {
return d.children.length;
} else {
return 0;
}
})]).nice();
// Update the x-axis.
svg.selectAll(".x.axis").transition()
.duration(duration)
.call(xAxis);
// Transition entering bars to their new position.
var enterTransition = enter.transition()
.duration(duration)
.delay(function(d,i) {
return i * delay;
})
.attr("transform",i) {
return "translate(0," + barHeight * i * 1.2 + ")";
});
// Transition entering text.
enterTransition.select("text")
.style("fill-opacity",1);
// Transition entering rects to the new x-scale.
enterTransition.select("rect")
.attr("width",function(d) {
if (d.height != 0) {
return x(d.children.length);
} else {
return x(0)
}
})
//.style("fill",function(d) { return color(!!d.children); });
.attr("fill",i) {
return color(i);
})
// Transition exiting bars to fade out.
var exitTransition = exit.transition()
.duration(duration)
.style("opacity",1e-6)
.remove();
// Transition exiting bars to the new x-scale.
exitTransition.selectAll("rect")
.attr("width",function(d) {
if (d.height != 0) {
return x(d.children.length);
} else {
return x(0)
}
});
// Rebind the current node to the background.
svg.select(".background")
.datum(d)
.transition()
.duration(end);
d.index = i;
}
function up(d) {
if (!d.parent || this.__transition__) return;
var end = duration + d.children.length * delay;
// Mark any currently-displayed bars as exiting.
var exit = svg.selectAll(".enter")
.attr("class","exit");
// Enter the new bars for the clicked-on data's parent.
var enter = bar(d.parent)
.attr("transform"," + barHeight * i * 1.2 + ")";
})
.style("opacity",1e-6);
// Color the bars as appropriate.
// Exiting nodes will obscure the parent bar,so hide it.
enter.select("rect")
//.style("fill",function(d) { return color(!!d.children); })
.attr("fill",i) {
return color(i);
})
.filter(function(p) {
return p === d;
})
.style("fill-opacity",1e-6);
// Update the x-scale domain.
x.domain([0,d3.max(d.parent.children,function(d) {
//console.log(d.height)
if (d.data.organisation_id) {
chart_title.text("Organisation Level")
}
if (d.data.aptcomplex_id) {
chart_title.text("Apartment Level")
} else if (d.data.building_id) {
chart_title.text("Building Level")
} else if (d.data.floor_id) {
chart_title.text("Floor Level")
} else if (d.data.unit_id) {
chart_title.text("Unit Level")
} else if (d.data.device_id) {
chart_title.text("Device Level")
}
if (d.height != 0) {
return d.children.length;
} else {
return 0;
}
})]).nice();
// Update the x-axis.
svg.selectAll(".x.axis").transition()
.duration(duration)
.call(xAxis);
// Transition entering bars to fade in over the full duration.
var enterTransition = enter.transition()
.duration(end)
.style("opacity",1);
// Transition entering rects to the new x-scale.
// When the entering parent rect is done,make it visible!
enterTransition.select("rect")
.attr("width",function(d) {
if (d.height != 0) {
return x(d.children.length);
} else {
return x(0);
}
})
.on("end",function(p) {
if (p === d) d3.select(this).style("fill-opacity",null);
});
// Transition exiting bars to the parent's position.
var exitTransition = exit.selectAll("g").transition()
.duration(duration)
.delay(function(d,stack(d.index));
// Transition exiting text to fade out.
exitTransition.select("text")
.style("fill-opacity",1e-6);
// Transition exiting rects to the new scale and fade to parent color.
exitTransition.select("rect")
.attr("width",function(d) {
if (d.height != 0) {
return x(d.children.length);
} else {
return x(0);
}
})
//.style("fill",color(true));
.attr("fill",i) {
return color(i);
})
// Remove exiting nodes when the last child has finished transitioning.
exit.transition()
.duration(end)
.remove();
// Rebind the current parent to the background.
svg.select(".background")
.datum(d.parent)
.transition()
.duration(end);
}
// Creates a set of bars for the given data node,at the specified index.
function bar(d) {
var bar = svg.insert("g",".y.axis")
.attr("class","enter")
.attr("transform","translate(0,5)")
.selectAll("g")
.data(d.children)
.enter().append("g")
.style("cursor",function(d) {
return !d.children ? null : "pointer";
})
.on("click",down);
bar.append("text")
.attr("x",-6)
.attr("y",barHeight / 2)
.attr("dy",".35em")
.style("text-anchor","end")
.text(function(d) {
return d.data.name;
});
bar.append("rect")
.attr("width",function(d) {
return x(d.value);
})
.attr("height",barHeight)
.on("mousemove",function(d) {
tooltip
.style("left",d3.event.pageX - 50 + "px")
.style("top",d3.event.pageY - 70 + "px")
.style("display","inline-block")
.html(d.data.name);
})
.on("mouSEOut",function(d) {
tooltip.style("display","none");
});
return bar;
}
// A stateful closure for stacking bars horizontally.
function stack(i) {
var x0 = 0;
return function(d) {
var tx = "translate(" + x0 + "," + barHeight * i * 1.2 + ")";
x0 += x(d.value);
return tx;
};
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<div id="barchartContainer"></div>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。