2017-02-11 2 views
3

Я использую d3.stack(), чтобы создать нормализованный сложный баркар.
Но у меня возникли проблемы с доступом к соответствующим значениям встроенного набора данных для всплывающей подсказки для мусора.D3v4 Stacked Barchart Tooltip

serie.selectAll("rect") 
    .data(function(d) { return d; }) 
    .enter().append("rect") 
     ... 
     .on("mousemove", function(d){ 
      let coords = d3.mouse(svg.node()); 
      tooltip.style("left", coords[0] + "px"); 
      tooltip.style("top", coords[1] - 70 + "px"); 
      tooltip.style("display", "inline-block"); 
      tooltip.html("HOW TO ACCESS DATA HERE?"); 
     }); 

d является Array[2] в этой точке со значениями, определяющими базовые/верха, d.data полный исходный объект данных, но не хватает информации, над которой стопкой серии я в настоящее время зависания.
В идеале я хочу подсказку, чтобы показать для набора данных, как {name:"item1", foo:10, bar:20}

value: 10 
percentage: 33% 

при наведении курсора над foo прямоугольнику.
Все примеры, которые я нашел, предназначены для D3v3, где вы можете просто использовать d.y для доступа к соответствующему значению, но это, похоже, больше не работает с D3v4.

+0

Первый аргумент ('d') в v4 точно такой же, как и в v3. Я предлагаю вам отправить сообщение [MCVE] (http://stackoverflow.com/help/mcve). –

+0

Тогда мое предположение о том, что это было связано с версией, было неправильным, тем не менее остается вопрос: откуда я узнаю, по какой прямой из серии я паря? В соответствии с этим примером (http://bl.ocks.org/mstanaland/6100713) это должно быть просто 'dy', но вот сценарий, где он не работает, поскольку' d' является массивом стека: https: // jsfiddle.net/vu624zrg/1/ – TommyF

ответ

5

Вы можете получить имя элемента доступ к данным родителя, и используя это имя, чтобы получить значение:

.on('mouseover', function(d, i) { 
    var thisName = d3.select(this.parentNode).datum().key; 
    var thisValue = d.data[thisName]; 
    var total = d.data.foo + d.data.bar; 
    tooltip.html("Name: " + thisName + "<br>Value: " + thisValue + "<br>Percentage: " + thisValue/total + "%"); 
}); 

Вот ваш код с этой модификацией:

var svg = d3.select("svg"), 
 
    margin = { 
 
     top: 20, 
 
     right: 60, 
 
     bottom: 30, 
 
     left: 40 
 
    }, 
 
    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 x = d3.scaleBand() 
 
    .rangeRound([0, width]) 
 
    .padding(0.1) 
 
    .align(0.1); 
 

 
var y = d3.scaleLinear() 
 
    .rangeRound([height, 0]); 
 
var stack = d3.stack() 
 
    .offset(d3.stackOffsetExpand); 
 

 
var colors = ["#FF0000", "#00FF00", "#0000FF"]; 
 

 
var data = [{ 
 
    name: "item1", 
 
    foo: 10, 
 
    bar: 20 
 
}, { 
 
    name: "item2", 
 
    foo: 50, 
 
    bar: 50 
 
}]; 
 

 
x.domain(data.map(function(d) { 
 
    return d.name; 
 
})); 
 

 
var serie = g.selectAll(".serie") 
 
    .data(stack.keys(["foo", "bar"])(data)) 
 
    .enter().append("g") 
 
    .attr("class", "serie") 
 
    .attr("fill", function(d, i) { 
 
     return colors[i]; 
 
    }); 
 

 

 
var tooltip = d3.select('#tooltip'); 
 

 
var rects = serie.selectAll("rect") 
 
    .data(function(d) { 
 
     return d; 
 
    }) 
 
    .enter().append("rect") 
 

 
rects.attr("x", function(d) { 
 
     return x(d.data.name); 
 
    }) 
 
    .attr("y", function(d) { 
 
     return y(d[1]); 
 
    }) 
 
    .attr("height", function(d) { 
 
     return y(d[0]) - y(d[1]); 
 
    }) 
 
    .attr("width", x.bandwidth()) 
 
    .on('mouseover', function(d, i) { 
 
     var thisName = d3.select(this.parentNode).datum().key; 
 
     var thisValue = d.data[thisName]; 
 
     var total = d.data.foo + d.data.bar; 
 
     tooltip.html("Name: " + thisName + "<br>Value: " + thisValue + "<br>Percentage: " + thisValue/total + "%"); 
 
    }); 
 

 
g.append("g") 
 
    .attr("class", "axis axis--x") 
 
    .attr("transform", "translate(0," + height + ")") 
 
    .call(d3.axisBottom(x)); 
 

 
g.append("g") 
 
    .attr("class", "axis axis--y") 
 
    .call(d3.axisLeft(y).ticks(10, "%"));
<script src="https://d3js.org/d3.v4.min.js"></script> 
 

 
<div id="tooltip">tooltip</div> 
 
<svg width="500" height="300"></svg>

+0

Большое спасибо, 'd3.select (this.parentNode) .datum(). key' была той частью, которую я не мог понять! – TommyF

 Смежные вопросы

  • Нет связанных вопросов^_^