我尝试结合多个鼠标事件,这些事件是我从https://www.d3-graph-gallery.com/graph/barplot_stacked_hover.html和https://www.d3-graph-gallery.com/graph/barplot_stacked_highlight.html中摘取的。
不幸的是,mousemove功能不起作用。如第一个示例所示,我想在鼠标后面显示“工具提示”。
// set the dimensions and margins of the graph
var margin = {
top: 10,
right: 30,
bottom: 20,
left: 50
},
width = 460 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3.select("#my_dataviz")
.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 + ")");
// Parse the Data
d3.csv("https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/data_stackedXL.csv").then(function(data) {
// List of subgroups = header of the csv files = soil condition here
var subgroups = data.columns.slice(1)
// List of groups = species here = value of the first column called group -> I show them on the X axis
var groups = d3.map(data, function(d) {
return (d.group)
}).keys()
// Add X axis
var x = d3.scaleBand()
.domain(groups)
.range([0, width])
.padding([0.2])
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).tickSizeOuter(0));
// Add Y axis
var y = d3.scaleLinear()
.domain([0, 120])
.range([height, 0]);
svg.append("g")
.call(d3.axisLeft(y));
// color palette = one color per subgroup
var color = d3.scaleOrdinal()
.domain(subgroups)
.range(d3.schemeSet2);
//stack the data? --> stack per subgroup
var stackedData = d3.stack()
.keys(subgroups)
(data)
// ----------------
// Highlight a specific subgroup when hovered
// ----------------
// ----------------
// Create a tooltip
// ----------------
var tooltip = d3.select("#my_dataviz")
.append("div")
.style("opacity", 0)
.attr("class", "tooltip")
.style("background-color", "white")
.style("border", "solid")
.style("border-width", "1px")
.style("border-radius", "5px")
.style("padding", "1px")
// What happens when user hover a bar
var mouseover = function(d) {
// what subgroup are we hovering?
var subgroupName = d3.select(this.parentNode).datum().key; // This was the tricky part
var subgroupValue = d.data[subgroupName];
// Reduce opacity of all rect to 0.2
d3.selectAll(".myRect").style("opacity", 0.2)
// Highlight all rects of this subgroup with opacity 0.8. It is possible to select them since they have a specific class = their name.
d3.selectAll("." + subgroupName)
.style("opacity", 1)
tooltip
.html("subgroup: " + subgroupName + "<br>" + "Value: " + subgroupValue)
.style("opacity", 1)
}
var mousemove = function(d) {
tooltip
.style("left", (d3.mouse(this)[0] + 90) + "px") // It is important to put the +90: other wise the tooltip is exactly where the point is an it creates a weird effect
.style("top", (d3.mouse(this)[1]) + "px")
}
// When user do not hover anymore
var mouseleave = function(d) {
// Back to normal opacity: 0.8
d3.selectAll(".myRect")
.style("opacity", 0.8)
tooltip
.style("opacity", 0)
}
// Show the bars
svg.append("g")
.selectAll("g")
// Enter in the stack data = loop key per key = group per group
.data(stackedData)
.enter().append("g")
.attr("fill", function(d) {
return color(d.key);
})
.attr("class", function(d) {
return "myRect " + d.key
}) // Add a class to each subgroup: their name
.selectAll("rect")
// enter a second time = loop subgroup per subgroup to add all rectangles
.data(function(d) {
return d;
})
.enter().append("rect")
.attr("x", function(d) {
return x(d.data.group);
})
.attr("y", function(d) {
return y(d[1]);
})
.attr("height", function(d) {
return y(d[0]) - y(d[1]);
})
.attr("width", x.bandwidth())
.attr("stroke", "grey")
.on("mouseover", mouseover)
.on("mousemove", mousemove)
.on("mouseleave", mouseleave)
})
<head>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js "></script>
</head>
<body>
<div id="my_dataviz"></div>
</body>