我目前正在尝试为d3中的交互式配对条形图创建工具提示,但是在获取x位置以便在svg上定位工具提示时遇到了麻烦。

这是显示问题的JSFiddle:注意yPosition更新,但是我不确定如何在鼠标悬停时为每个栏获得正确的xPosition

我的代码如下:

$(document).ready(function(){
//Graph
var e = $('#graph');

//Get width of graph div
var w = document.getElementById('graph').clientWidth;

//Set margins, width and height of graph
var margin = {top: 40, right: 20, bottom: 30, left: 40}, width = w - margin.left - margin.right -10, height = 500 - margin.top - margin.bottom;

//Sca;e amd ramge
var x = d3.scale.ordinal()
    .rangeRoundBands([0, width], .1);
var x1 = d3.scale.ordinal();

var y = d3.scale.linear()
    .range([height, 0]);

//Define x and y axis
var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom");

var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left");

//Generate svg element in graph div
var svg = d3.select("#graph").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 + ")");

//Redraw graph on window resize
function updateWindow(){
    x = w.innerWidth || e.clientWidth || g.clientWidth;
    y = w.innerHeight|| e.clientHeight|| g.clientHeight;

    svg.attr("width", x).attr("height", y);
}
window.onresize = updateWindow;

//Access output data to populate graph
d3.csv("inputs/outputs/Milk_Month2.csv",type, function(error, data) {
    //Graph colors
    var color = d3.scale.ordinal().range(["#98abc5", "#8a89a6"]);
    //data attributes for the two different graphs
    var categoryNamesMilk = d3.keys(data[0]).filter(function(key) { return key !== "month" && key !== "water_current" && key !== "water_future" ; });
    var categoryNamesWater = d3.keys(data[0]).filter(function(key) { return key !== "month" && key !== "milk_current" && key !== "milk_future" ; });

    data.forEach(function(d) {
        d.categoriesMilk = categoryNamesMilk.map(function(name) { return {name: name, value: +d[name]}; });
        d.categoriesWater = categoryNamesWater.map(function(name) { return {name: name, value: +d[name]}; });
    });

    x.domain(data.map(function(d) { return d.month; }));
    x1.domain(categoryNamesMilk).rangeRoundBands([0, x.rangeBand()]);
    y.domain([0, d3.max(data, function(d) { return d3.max(d.categoriesMilk, function(d) { return d.value; }); })]);

    //Generate X Axis
    var axisX = svg.append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0," + height + ")")
        .call(xAxis);

    //Generate Y Axis
    var axisY = svg.append("g")
        .attr("class", "y axis")
        .call(yAxis)
        .append("text")
        .attr("transform", "rotate(-90)")
        .attr("y", 6)
        .attr("dy", ".71em")
        .style("text-anchor", "end")
        .text("Milk Production (KG/Day)").attr("class","yaxis-text");

    var infoBars = svg.selectAll(".bar")
        .data(data)
        .enter().append("g")
        .attr("class", "g")
        .attr("transform", function(d,i) {console.log(x(d.month),i); return "translate(" + x(d.month) + ",0)"; });

    infoBars.selectAll("rect")
        .data(function(d) { return d.categoriesMilk; })
        .enter().append("rect")
        .attr("width", x1.rangeBand())
        .attr("x", function(d) { return x1(d.name); })
        .attr("y", function(d) { return y(d.value); })
        .attr("height", function(d) { return height - y(d.value); })
        .style("fill", function(d) { return color(d.name); })
        .on("mouseover", function(d,i) {

        //Where I'm having problems - getting the X attribute!
        var xPosition = parseFloat(x(i) + x1.rangeBand());
        var yPosition = parseFloat(d3.select(this).attr("y")) / 2 + height / 2;

        //Update the tooltip position and value
        d3.select("#tooltip")
            .style("left", xPosition + "px")
            .style("top", yPosition + "px")
            .select("#value")
            .text(d.value);
            //Show the tooltip
            d3.select("#tooltip").classed("hidden", false);

    }).on("mouseout", function() {
        //Hide the tooltip
        d3.select("#tooltip").classed("hidden", true);
    });


});

//Data type conversion
function type(d) {
    d.milk_current = +d.milk_current;
    d.water_current = +d.water_current;
    d.milk_future = +d.milk_future;
    d.water_future = +d.water_future;

  return d;
}

});


它是从csv提取的,如下所示(我还有一个click函数,可转换为第二个配对图,因此还有其他数据列

month,water_current,milk_current,water_future,milk_future
1,2.259,1.955,2.4849,100
2,0.006,0,0.0066,0
3,14.443,11.795,15.8873,10.6155
4,2.87,21.538,3.157,19.3842
5,0,20.216,1,18.1944
6,0.973,18.37,1.0703,16.533
7,1.492,15.686,1.6412,14.1174
8,0,13.146,0.5,11.8314
9,0,12.087,0.4,10.8783
10,0,9.626,0.3,8.6634
11,7.434,8.19,8.1774,7.371
12,6.049,7.207,6.6539,6.4863


我很确定我需要在鼠标悬停时访问每个“矩形”的父元素并检索x位置,但是这样做没有任何运气...任何建议吗?

最佳答案

您可以像以下方式访问每个g的父rect

.on("mouseover", function(d,i) {
    var parentG = d3.select(this.parentNode);


要获得X值:

var barPos = parseFloat(parentG.attr('transform').split("(")[1]);


x位置变为:

var xPosition = barPos + x1(d.name);


小提琴here

09-13 09:59