简体   繁体   English

如何使用 D3.js v5 访问数组中的特定数据以获得堆叠条形图工具提示

[英]how to access specific data in an array using D3.js v5 for a stacked bar graph tooltip

I have a JSON file below.我在下面有一个 JSON 文件。 I'm adding all the values together in field 1 and all the values in field 2 etc... then trying to get the total amount shown on a tooltip.我将字段 1 中的所有值和字段 2 中的所有值等相加......然后尝试获取工具提示上显示的总量。 So when I hover over each 'rect', I have a total field amount as well as group amounts.因此,当我将鼠标悬停在每个“矩形”上时,我有一个总字段数量以及组数量。

    [
  {
    "group": "Field 1",
    "0-45": 12345,
    "46-65": 91568,
    "66-85": 13087,
    "85+": 7045
  },
  {
    "group": "Field 2",
    "0-45": 62345,
    "46-65": 15347,
    "66-85": 37688,
    "85+": 7007
  }
]

Here is the sample code...这是示例代码...

let totalColVal = d3.nest()
  .key(function(d){return (d.group)})   
  .rollup(function(totals){
    return d3.sum(totals, function(d) {return d3.sum(d3.values(d))})
  }).entries(data)

  console.log(totalColVal)

This returns这返回

(4) [{…}, {…}, {…}, {…}]
0: {key: "Field 1", value: 124045}
1: {key: "Field 2", value: 122387}
2: {key: "Field 3", value: 172041}
3: {key: "Field 4", value: 67594}

Above gets the total amount for each field, but how do I get the tooltip to show each value when I hover over each rect.以上获取每个字段的总数,但是当我将鼠标悬停在每个矩形上时,如何获取工具提示以显示每个值。

  //tooltip
  let mouseover = function(d) {
    let subgroupName = d3.select(this.parentNode).datum().key;
      // console.log(subgroupName)
    let subgroupValue = d.data[subgroupName];
      // console.log(subgroupValue)    
  
    tooltip.html('<b>Field:</b> <span style="color:yellow">' + d.data.group + '</span>' + '<br>\
      ' + '<b>Count:</b> <span style="color:yellow">' + formater(subgroupValue) + '</span>' + '<br>\
      ' + ' <b>Size Band:</b> <span style="color:yellow">' + subgroupName + '</span>' + '<br>\
      ' + '<b>Field Total:</b>  <span style="color:yellow">' + totalColVal + '</span>')
        .style("opacity", 1)
  };
  let mousemove = function(d) {
    tooltip.style('left', (d3.event.pageX - 70) + 'px')
      .style('top', (d3.event.pageY - 85) + 'px')
  };
  let mouseleave = function(d) {
    tooltip.style("opacity", 0)
  };

totalColVal returns [object Object],[object Object],[object Object],[object Object] on my tooltip. totalColVal 在我的工具提示上返回 [object Object],[object Object],[object Object],[object Object]。

Assistance will be very much appreciated.非常感谢您的帮助。

JS fiddle here JS小提琴在这里

To get the value from the i th bar, there is actually a second argument, next to d , that you can access in all d3 functions.要从第i个条形图中获取值,实际上在d旁边还有第二个参数,您可以在所有 d3 函数中访问它。 i denotes the index of that element in the array you passed it. i表示该元素在您传递给它的数组中的索引。

I changed the mouseover function to just use i here, and it resolved your issue:我将鼠标悬停功能更改为仅在此处使用i ,它解决了您的问题:

 const canvas = d3.select('#stacked'); const stackedSvg = canvas.append('svg') .attr('preserveAspectRatio', 'xMinYMin meet') .attr('viewBox', '0 0 900 500') .classed('svg-content', true); let margin = {top: 40, right: 30, bottom: 20, left: 70}, width = 260 - margin.left - margin.right, height = 250 - margin.top - margin.bottom; // append the svg object to the body of the page let svg = stackedSvg.append('g') .attr('width', width) .attr('height', height) .attr('transform', `translate(${margin.left}, ${margin.top})`); //number formater const formater = d3.format(',d'); let myData = [ { "group": "Field 1", "0-45": 12345, "46-65": 91568, "66-85": 13087, "85+": 7045 }, { "group": "Field 2", "0-45": 62345, "46-65": 15347, "66-85": 37688, "85+": 7007 }, { "group": "Field 3", "0-45": 11457, "46-65": 28456, "66-85": 124564, "85+": 7564 }, { "group": "Field 4", "0-45": 19234, "46-65": 26754, "66-85": 14153, "85+": 7453 } ] //tooltip let tooltip = d3.select('body').append('div') .attr('class', 'tooltip') .style('opacity', 0); // Parse the Data Promise.resolve(myData) .then(data => { // console.log(data); //select the size bands let keys = d3.keys(data[0]).slice(1); // console.log(keys); // List of groups in JSON. value of the first column called group let groups = d3.map(data, function(d){return(d.group)}).keys(); // console.log(groups); // X axis let 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)); svg.append('text') .attr('class', 'xLabel') .attr('text-anchor', 'end') .attr('x', width / 2 + 20) .attr('y', height + 30) .text('Size Band') .style('font-size', 10); // Y axis let y = d3.scaleLinear() .domain([0, d3.max(data, d => d3.sum(keys, k => +d[k]))]) .range([ height, 0 ]); svg.append('g') .call(d3.axisLeft(y) .tickSizeOuter(0) .tickSizeInner(- width) .tickPadding(5)) .selectAll(".tick") .style("stroke-dasharray", ("1, 1")) //dash line across graph. .each(function (d, i) { if ( d == 0 ) { this.remove(); } }); svg.append('text') .attr('class', 'yLabel') .attr('transform', 'rotate(-90)') .attr('y', - 40) .attr('x', - height / 2 + 20) .attr('text-anchor', 'end') .text('Units') .style('font-size', 10); // color let color = d3.scaleOrdinal() .domain(keys) .range(['brown', 'steelblue', 'olivedrab', 'darkorange']); //stack the data --> stack per subgroup let stackedData = d3.stack() .keys(keys) (data); console.log(stackedData) let totalColVal = d3.nest() .key(function(d){return (d.group)}) .rollup(function(totals){ return d3.sum(totals, function(d) {return d3.sum(d3.values(d))}) }).entries(data) console.log(totalColVal) //tooltip let mouseover = function(d, i) { let subgroupName = d3.select(this.parentNode).datum().key; // console.log(subgroupName) let subgroupValue = d.data[subgroupName]; // console.log(subgroupValue) tooltip.html('<b>Field:</b> <span style="color:yellow">' + d.data.group + '</span>' + '<br>\\ ' + '<b>Count:</b> <span style="color:yellow">' + formater(subgroupValue) + '</span>' + '<br>\\ ' + ' <b>Size Band:</b> <span style="color:yellow">' + subgroupName + '</span>' + '<br>\\ ' + '<b>Field Total:</b> <span style="color:yellow">' + totalColVal[i].value + '</span>') .style("opacity", 1) }; let mousemove = function(d) { tooltip.style('left', (d3.event.pageX - 70) + 'px') .style('top', (d3.event.pageY - 85) + 'px') }; let mouseleave = function(d) { 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) }) .selectAll('rect') // enter a second time = loop subgroup per subgroup to add all rectangles .data(function(d) { return d; }) .enter().append('rect') .on('mouseover', mouseover) .on('mousemove', mousemove) .on('mouseleave', mouseleave) .transition() .attr('y', d => y(d.height)) .delay(function(d, i) { return i * 100 }) .ease(d3.easeLinear) .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()) .style('stroke', 'black') .style('opacity', 0.9); });
 body { font-family: halyard-display, sans-serif; /* background-color: black; */ } div.tooltip { position: absolute; text-align: left; width: fit-content; height: fit-content; padding: 5px 5px; font-size: 16px; background:rgb(24, 23, 23); color: white; border-radius: 5px; pointer-events: none; } .yLabel { fill: #DEDC00; font-style: italic; font-weight: 600; } .xLabel { fill: #DEDC00; font-style: italic; font-weight: 600; } g .tick text { font-size: 8px; color: grey; } g .tick text:hover { font-size: 12px; } g .tick { color: #DEDC00; }
 <script src="https://d3js.org/d3.v5.js"></script> <div id="stacked"></div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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