简体   繁体   中英

Having trouble adding a tooltip to my D3 bar chart?

I'm working on a fairly simple bar chart and want to add a tooltip so that when a user hovers over each individual bar they can see the exact Size of the technology (values on y-axis). After much research online I still cannot get it to work. I'm now using d3-tip ( https://openbase.com/js/d3-tip/documentation ) which has tutorials that seem to make the process easier but still no luck. Any help on this issue would be greatly appreciated. I've attached my.js and.html files below. Thank you!

Javascript

import * as d3 from "d3";
import d3Tip from "d3-tip";
d3.tip = d3Tip;

// DATA //

let data = [
  {
    Technology: "Hydropower",
    Size: 33,
    Carbon: 350
  },
  {
    Technology: "Coal",
    Size: 15,
    Carbon: 754
  },
  {
    Technology: "Ground PV",
    Size: 19,
    Carbon: 905
  },
  {
    Technology: "Large Hydropower",
    Size: 14,
    Carbon: 142
  },
  {
    Technology: "Roof Solar",
    Size: 3,
    Carbon: 263
  },
  {
    Technology: "Nuclear",
    Size: 0.3,
    Carbon: 475
  },
  {
    Technology: "Ethanol",
    Size: 50.3,
    Carbon: 374
  },
  {
    Technology: "Onshore Wind",
    Size: 0.4,
    Carbon: 224
  }
];

// PLOTTING //

const svg = d3.select("svg"),
  margin = { top: 100, right: 20, bottom: 100, left: 20 },
  width = svg.attr("width") - margin.left - margin.right,
  height = svg.attr("height") - margin.top - margin.bottom;

const xScale = d3.scaleBand().range([0, width]).padding(0.4),
  yScale = d3.scaleLinear().range([height, 0]);

const g = svg
  .append("g")
  .attr("transform", "translate(" + 100 + "," + 100 + ")");

xScale.domain(
  data.map(function (d) {
    return d.Technology;
  })
);
yScale.domain([
  0,
  d3.max(data, function (d) {
    return d.Size;
  })
]);

g.append("g")
  .attr("transform", "translate(0," + height + ")")
  .call(d3.axisBottom(xScale));

g.append("g")
  .call(
    d3
      .axisLeft(yScale)
      .tickFormat(function (d) {
        return d + " kW";
      })
      .ticks(10)
  )
  .append("text")
  .attr("y", 6)
  .attr("dy", "0.71em")
  .attr("text-anchor", "end");

g.append("text")
  .attr("transform", "translate(" + width / 2 + " ," + (height + 40) + ")")
  .style("text-anchor", "middle")
  .text("Technology");

g.append("text")
  .attr("transform", "rotate(-90)")
  .attr("x", 0 - height / 2)
  .attr("y", 0 - margin.left - 40)
  .style("text-anchor", "middle")
  .text("Size (kW)");

// var tip = d3
//   .tip()
//   .attr("class", "d3-tip")
//   .html(function (d) {
//     return (
//       "<strong>Size:</strong> <span style='color:red'>" + d.Size + "</span>"
//     );
//   });

g.selectAll("bar")
  .data(data)
  .enter()
  .append("g")
  .attr("class", "bar")
  .append("rect")
  .attr("x", function (d) {
    return xScale(d.Technology);
  })
  .attr("y", function (d) {
    return yScale(d.Size);
  })
  .attr("width", xScale.bandwidth())
  .attr("height", function (d) {
    return height - yScale(d.Size);
  });
// .on("mouseover", tip.show)
// .on("mouseout", tip.hide);

HTML

<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" href="style.css" />
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Sofia">

    <title>Land Usage Comparison</title>
    <meta charset="UTF-8" />

    <script src="d3.min.js"></script>
    <script src="land.js"></script>
  </head>

  <body>
    <header>
      <h1>
        Land Usage Comparison
        <!-- <img src="logo.svg" alt="Discover the World" -->
      </h1>

      <p name="valueX" id="landusage">
        <label
          ><input type="checkbox" name="elecprod" value="1" /><span
            >ELectricity Produced</span
          ></label
        >
        <label
          ><input type="checkbox" name="carbonemissions" value="2" /><span
            >Carbon Emissions</span
          ></label
        >
      </p>

      <p></p>
    </header>

    <svg width="960" height="600"></svg>

    <div id="tooltip" class="hidden">
      <p><strong>Size Value</strong></p>
      <p><span id="value">100</span><p>
    </div>

  </body>
</html>

Sorry, I can't resolve exactly your problem, but if you just want to show a tooltip for bar-chart using D3 lib. Please check this tutorial: Animated bar chart with D3

Maybe, it doesn't depend on d3-tip lib. Checking two events are: .on("mouseover", onMouseOver) and .on("mouseout", onMouseOut) .

In my opinion, you must custom onMouseOver when a user hovers over each individual, and custom onMouseOut when a user hovers out a bar.

Please, attention to these two functions:

function onMouseOver(d, i) {

d3.select(this).attr('class', 'highlight');
d3.select(this)
  .transition()
  .duration(400)
  .attr('width', x.bandwidth() + 5)
  .attr("y", function(d) { return y(d.value) - 10; })
  .attr("height", function(d) { return height - y(d.value) + 10; });

g.append("text")
 .attr('class', 'val') // add class to text label
 .attr('x', function() {
     return x(d.year);
 })
 .attr('y', function() {
     return y(d.value) - 15;
 })
 .text(function() {
     return [ '$' +d.value];  // Value of the text
 });
}

function onMouseOut(d, i) {
    d3.select(this).attr('class', 'bar');
    d3.select(this)
      .transition()
      .duration(400)
      .attr('width', x.bandwidth())
      .attr("y", function(d) { return y(d.value); })
      .attr("height", function(d) { return height - y(d.value); });

    d3.selectAll('.val')
      .remove()
}

And finally, add it to build a chart

g.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.on("mouseover", onMouseOver)
.on("mouseout", onMouseOut)
.attr("x", function(d) { return x(d.year); })
.attr("y", function(d) { return y(d.value); })
.attr("width", x.bandwidth())
.transition()
.ease(d3.easeLinear)
.duration(400)
.delay(function (d, i) {
    return i * 50;
})
.attr("height", function(d) { return height - y(d.value); });

Remember to handle it and I hope that it can help you. Good luck,

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM