我正在用d3.js(v4)绘制分组的条形图。在此,我已将工具提示作为超链接。
我的要求:当我将鼠标悬停在工具提示上时,在代码中,它应该返回相应的钢筋组x轴刻度值,通过该值,我会将工具提示网址设置为唯一的html文件。
我也可以使用“ data 1。week”来获取xtick值。但是,它并没有达到目的,因为我需要在运行时使用工具提示悬停行为来映射此值。
CSV文件
Week,Total,Pass,Fail
w-32,4,4,0
w-33,2,1,1
w-34,2,0,2
w-37,2,1,1
w-38,1,1,0
w-39,1,1,0
工作代码
<!DOCTYPE html>
<html>
<meta http-equiv="content-type" content="text/html; charset=UTF8">
<style>
@-webkit-keyframes bounceIn {
0% {
opacity: 0;
-webkit-transform: scale(.3);
}
50% {
opacity: 1;
-webkit-transform: scale(1.05);
}
70% {
-webkit-transform: scale(.9);
}
100% {
-webkit-transform: scale(1);
}
}
@keyframes bounceIn {
0% {
opacity: 0;
transform: scale(.3);
}
50% {
opacity: 1;
transform: scale(1.05);
}
70% {
transform: scale(.9);
}
100% {
transform: scale(1);
}
}
.d3-tip.animate {
animation: bounceIn 0.2s ease-out;
-webkit-animation: bounceIn 0.2s ease-out;
}
.d3-tip span {
color: #ff00c7;
}
.d3-tip {
line-height: 1;
font-weight: bold;
padding: 8px;
background: #FFE4C4;
color: white;
border-radius: 2px;
text-decoration: none;
}
/* Creates a small triangle extender for the tooltip */
.d3-tip:after {
<!--box-sizing: border-box;-->
display: inline;
font-size: 10px;
width: 100%;
line-height: 1;
color: #FFE4C4;
content: "\25BC";
position: absolute;
text-align: center;
}
/* Style northward tooltips differently */
.d3-tip.n:after {
margin: -1px 0 0 0;
top: 100%;
left: 0;
}
<!-- For setting overall graph dimensions:Start -->
</style>
<body>
<svg width="600" height="400"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.7.1/d3-tip.min.js"></script>
<script>
labels = ["Total", "Pass", "Fail"];
<!-- For setting overall graph dimensions:End -->
<!-- For setting graph margins:Start -->
var svg = d3.select("svg"),
margin = {top: 33, right: 10,bottom: 150, left: 24},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var colour = ["#a9a9a9", "#66cc00", "#ff3333"]
<!-- For gaping between bar groups-->
var x0 = d3.scaleBand()
.rangeRound([0, width])
.paddingInner(0.2);
<!-- For gaping between bars in groups-->
var x1 = d3.scaleBand()
.padding(0.01);
var y = d3.scaleLinear()
.rangeRound([height, 0]);
var z = d3.scaleOrdinal()
.range(["#a9a9a9", "#66cc00", "#ff3333"]);
var timeout;
<!--Data read from csv and plot grouped bar chart-->
d3.csv("weekwise.csv", function(d, i, columns) {
for (var i = 1, n = columns.length; i < n; ++i) d[columns[i]] = +d[columns[i]];
return d;
}, function(error, data) {
if (error) throw error;
<!--console.log(data.length);-->
var tool_tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-8, 0])
.html(function(d) {
#Help needed here
#This is where tool tip is getting set dynamically. However, all the bar are poiting to same html file.
#I'll let each bar point to unique html file dynamically, if get the xtick value
return '<a href= '+"wk"+31+"-"+d.key+"-"+d.value+".html" +' target="_parent">' + d.value + "</a>";
}
})
svg.call(tool_tip)
var keys = data.columns.slice(1);
x0.domain(data.map(function(d) { return d.Week; }));
<!--console.log(x0(d.Week));-->
x1.domain(keys).rangeRound([0, x0.bandwidth()]);
y.domain([0, d3.max(data, function(d) { return d3.max(keys, function(key) { return d[key]; }); })]).nice();
g.append("g")
.selectAll("g")
.data(data)
.enter().append("g")
.attr("transform", function(d) { return "translate(" + x0(d.Week) + ",0)"; })
.selectAll("rect")
.data(function(d) { return keys.map(function(key) { return {key: key, value: d[key]}; }); })
.enter().append("rect")
.attr("x", function(d) { return x1(d.key); })
.attr("y", function(d) { return y(d.value); })
.attr("width", x1.bandwidth())
.attr("height", function(d) { return height - y(d.value); })
.attr("fill", function(d) { return z(d.key); })
<!--// Tooltip stuff after this-->
.on('mouseover', function(d) {
<!--console.log(d);-->
var context = this;
var args = [].slice.call(arguments);
args.push(this);
clearTimeout(timeout);
timeout = setTimeout(function() {
tool_tip.show.apply(context, args);
}, 800);
})
<!--.on('mouseout', tool_tip.hide)-->
.on('mouseout', function(d) {
var context = this;
var args = [].slice.call(arguments);
args.push(this);
clearTimeout(timeout);
timeout = setTimeout(function() {
tool_tip.hide.apply(context, args);
}, 2000);
})
g.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x0));
console.log(g);
<!--Code for adding graph title-->
g.append("g")
.attr("class", "axis")
.call(d3.axisLeft(y).ticks(null, "s"))
.append("text")
.attr("x", (width / 2))
.attr("y", 0 - (margin.top / 1.5))
.attr("fill", "#000")
.attr("text-anchor", "middle")
.style("font-size", "14px")
.style("font-weight", "bold")
<!--.style("text-decoration", "underline")-->
.text("Build Statistics-v8.0.18");
<!--Code for defining and appending legend-->
var legend = g.append("g")
.attr("class", "legend")
.attr("height", 100)
.attr("width", 100)
.attr('transform', 'translate(-5,' + (height + 50) + ')')
.style("font", "12px sans-serif");
legend.selectAll('rect')
.data(labels)
.enter()
.append("rect")
.attr("x", function(d, i){
var xPost = legendXPosition(labels, i, 6);
return xPost;
})
.attr("y", -12)
.attr("width", 12)
.attr("height", 12)
.style("fill", function(d, i) {
var color = colour[i];
return color;
});
legend.selectAll('text')
.data(labels)
.enter()
.append("text")
.attr("x", function(d, i){
var xPost = legendXPositionText(labels, i, 22, 6);
return xPost;
})
.attr("y", -1)
.text(function(d) {
return d;
});
function legendXPositionText(data, position, textOffset, avgFontWidth){
return legendXPosition(data, position, avgFontWidth) + textOffset;
}
function legendXPosition(data, position, avgFontWidth){
if(position == 0){
return 0;
} else {
var xPostiion = 0;
for(i = 0; i < position; i++){
xPostiion += (data[i].length * avgFontWidth + 40);
}
return xPostiion;
}
}
});
</script>
</body>
</html>
请查看使用以上代码生成的图形。
答案 0 :(得分:1)
d3-tip
不允许对数据或节点进行太多摆弄,因此,您不得不坚持让d3-tip
从触发它的节点返回数据(在此情况下,您会丢失父节点)或父节点(您将无法获得有关悬停在哪个节点上的信息)。解决方案是将更多数据添加到每个节点(即在绑定到每个节点的数据中包括星期),或者在将鼠标悬停在节点上时动态提取星期数据,例如:
.on('mouseover', function(d) {
// if d.parent isn't defined, get the parent node of the current selection
// and add that data to the current node
if ( ! d.parent ) {
d.parent = d3.select( this.parentNode ).datum();
}
tool_tip.show(d);
}
如果您尝试以其他方式操纵tip.show()
的参数,则由于d3-tip
在内部使用参数,会引发其他错误;它们并没有像您想象的那样直接传递给tip.html()
函数。
您最好将周数据包括在绑定数据中来规避这一点,但是:
.data(function(d) {
return keys.map(function(key) { return {key: key, value: d[key], week: d.Week }; });
})
答案 1 :(得分:-1)
是否考虑过将周数添加到绑定数据中?
.data(d => keys.map(key => ( {key: key, value: d[key], week:d.Week.slice(2)} )) )