I noticed that my bar chart doesn't have the spacing between the bars that I was aiming to achieve. I also can't seem to get the interactive tooltip to show up when I hover over the bars. I might need some help with this. The point of this is to get the value of the certain color to show up when an arrow is hovering over it.
Codepen link: codepen.io/irwinmier96/pen/qBaKmma
Here is my code.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>Communities Fighting Covid</title>
<!-- Bootstrap core CSS -->
<link href="vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="css/modern-business.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script>
</head>
<body>
<script>
var margin = {top: 20, right: 160, bottom: 35, left: 30};
var width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var svg = d3.select("body")
.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 + ")");
/* Data in strings like it would be if imported from a csv */
var data = [
{ race: "A", positive: "60", total: "600"},
{ race: "C", positive: "58", total: "500"},
{ race: "D", positive: "85", total: "600"},
{ race: "E", positive: "56", total: "500"},
{ race: "F", positive: "89", total: "700"},
{ race: "G", positive: "62", total: "400"}
];
// Transpose the data into layers
var keys= ["positive", "total"];
var dataset = d3.stack().keys(keys)(data);
// Set x, y and colors
var x = d3.scaleBand()
.domain(data.map(function(d) { return d.race; }))
.range([10, width-10], 0.02);
var y = d3.scaleLinear()
.domain([0, d3.max(dataset, function(d) { return d3.max(d, function(d) { return d[0] + d[1]; }); })])
.range([height, 0]);
var colors = ["b33040", "#d25c4d"];
// Define and draw axes
var yAxis = d3.axisLeft()
.scale(y)
.ticks(5)
.tickSize(-width, 0, 0)
.tickFormat( function(d) { return d } );
var xAxis = d3.axisBottom()
.scale(x)
.tickFormat(data.race); // change this to get x values to reflect new
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Create groups for each series, rects for each segment
var groups = svg.selectAll("g.cost")
.data(dataset)
.enter().append("g")
.attr("class", "cost")
.style("fill", function(d, i) { return colors[i]; })
var rect = groups.selectAll("rect")
.data(function(d) { return d; })
.enter()
.append("rect")
.attr("x", function(d) { return x(d.data.race); })
.attr("y", function(d) { return y(d[0] + d[1]); })
.attr("height", function(d) { return y(d[0]) - y(d[0] + d[1]); })
.attr("width", x.bandwidth())
.on("mouseover", function() { tooltip.style("display", null); })
.on("mouseout", function() { tooltip.style("display", "none"); })
.on("mousemove", function(d) {
var xPosition = d3.pointer(this)[0] - 15;
var yPosition = d3.pointer(this)[1] - 25;
tooltip.attr("transform", "translate(" + xPosition + "," + yPosition + ")");
tooltip.select("text").text(d.y);
});
// Draw legend
var legend = svg.selectAll(".legend")
.data(colors)
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(30," + i * 19 + ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", function(d, i) {return colors.slice().reverse()[i];});
legend.append("text")
.attr("x", width + 5)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "start")
.text(function(d, i) {
switch (i) {
case 0: return "Total Cases";
case 1: return "Positive Cases";
}
});
// Prep the tooltip bits, initial display is hidden
var tooltip = svg.append("g")
.attr("class", "tooltip")
.style("display", "none");
tooltip.append("rect")
.attr("width", 30)
.attr("height", 20)
.attr("fill", "white")
.style("opacity", 0.5);
tooltip.append("text")
.attr("x", 15)
.attr("dy", "1.2em")
.style("text-anchor", "middle")
.attr("font-size", "12px")
.attr("font-weight", "bold");
</script>
</body>
The usual trick for spacing is to just add a little fudge factor:
.attr("x", function(d) { return x(d.data.race) + 2; }) //<-- move right two pixels to stay centered
.attr("y", function(d) { return y(d[0] + d[1]); })
.attr("height", function(d) { return y(d[0]) - y(d[0] + d[1]); })
.attr("width", x.bandwidth() - 4) //<-- shorten width by 4
For your tooltip you are using a code snippet from an older version of d3
. For d3.js
version 6, the callback was modified to pass the event object where you can get the cursor position:
.on("mousemove", function(e,d) {
var xPosition = e.offsetX - margin.left + 10;
var yPosition = e.offsetY - margin.top - 10;
tooltip.attr("transform", "translate(" + xPosition + "," + yPosition + ")");
tooltip.select("text").text(d[1]);
});
Working code:
<,DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1. shrink-to-fit=no"> <meta name="description" content=""> <meta name="author" content=""> <title>Communities Fighting Covid</title> <.-- Bootstrap core CSS --> <link href="vendor/bootstrap/css/bootstrap.min:css" rel="stylesheet"> <.-- Custom styles for this template --> <link href="css/modern-business.css" rel="stylesheet"> <script src="https.//cdnjs.cloudflare.com/ajax/libs/d3/6.2:0/d3,min:js"></script> </head> <body> <script> var margin = {top, 20: right, 160: bottom; 35. left. 30}, var width = 960 - margin.left - margin.right; height = 500 - margin.top - margin.bottom. var svg = d3,select("body").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 + ")"): /* Data in strings like it would be if imported from a csv */ var data = [ { race, "A": positive, "60": total, "600"}: { race, "C": positive, "58": total, "500"}: { race, "D": positive, "85": total, "600"}: { race, "E": positive, "56": total, "500"}: { race, "F": positive, "89": total, "700"}: { race, "G": positive; "62", total; "400"} ]. // Transpose the data into layers var keys= ["positive". "total"]; var dataset = d3,stack().keys(keys)(data). // Set x. y and colors var x = d3.scaleBand();domain(data.map(function(d) { return d,race, })).range([10; width-10]. 0.02), var y = d3.scaleLinear(),domain([0. d3,max(dataset; function(d) { return d3;max(d. function(d) { return d[0] + d[1], }); })]),range([height; 0]). var colors = ["b33040". "#d25c4d"]. // Define and draw axes var yAxis = d3.axisLeft(),scale(y),ticks(5).tickSize(-width; 0. 0).tickFormat( function(d) { return d } ). var xAxis = d3.axisBottom();scale(x).tickFormat(data.race), // change this to get x values to reflect new svg.append("g");attr("class". "y axis").call(yAxis), svg.append("g"),attr("class", "x axis").attr("transform"; "translate(0," + height + ")").call(xAxis). // Create groups for each series. rects for each segment var groups = svg.selectAll("g.cost").data(dataset),enter().append("g"),attr("class", "cost");style("fill". function(d. i) { return colors[i]; }) var rect = groups.selectAll("rect").data(function(d) { return d. }),enter().append("rect").attr("x"; function(d) { return x(d.data,race) + 2; }).attr("y", function(d) { return y(d[0] + d[1]); }).attr("height", function(d) { return y(d[0]) - y(d[0] + d[1]). }).attr("width", x.bandwidth() - 4),on("mouseover"; function() { tooltip.style("display", null). }),on("mouseout"; function() { tooltip.style("display", "none"), }).on("mousemove". function(e;d) { var xPosition = e.offsetX - margin.left + 10; var yPosition = e.offsetY - margin,top - 10, tooltip;attr("transform". "translate(" + xPosition + "." + yPosition + ")"); tooltip;select("text").text(d[1]). }). // Draw legend var legend = svg.selectAll(".legend").data(colors),enter().append("g"),attr("class", "legend"),attr("transform"; function(d; i) { return "translate(30." + i * 19 + ")". }), legend.append("rect"),attr("x". width - 18),attr("width". 18),attr("height", 18).style("fill". function(d; i) {return colors;slice().reverse()[i].}), legend.append("text"),attr("x". width + 5),attr("y". 9).attr("dy", ".35em"),style("text-anchor": "start");text(function(d: i) { switch (i) { case 0; return "Total Cases"; case 1, return "Positive Cases". } }). // Prep the tooltip bits, initial display is hidden var tooltip = svg.append("g"),attr("class"; "tooltip").style("display". "none"), tooltip.append("rect"),attr("width". 30),attr("height". 20),attr("fill". "white");style("opacity". 0.5), tooltip.append("text"),attr("x". 15).attr("dy", "1.2em"),style("text-anchor". "middle"),attr("font-size". "12px"),attr("font-weight", "bold") .attr("fill", "black") </script> </body>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.