2015-11-04 111 views
1

我很難根據y軸刻度值繪製水平網格。我可以在y軸上繪製網格,但不能根據Y軸座標進行繪製。如何根據D3中的y軸刻度繪製水平網格?

Bar chart

Here is my fiddle

var data = [["Since Mar 10, 2015",150], ["1 year",-17.1], ["3 year",6.9],["Since Mar 10, 2010",100]]; 


d3.select("#example") 
.datum(data) 
.call(columnChart() 
.width(320) 
.height(240) 
.x(function(d, i) { return d[0]; }) 
.y(function(d, i) { return d[1]; })); 

function columnChart() { 
var margin = {top: 30, right: 10, bottom: 50, left: 50}, 
    width = 20, 
    height = 20, 
    xRoundBands = 0.6, 
    xValue = function(d) { return d[0]; }, 
    yValue = function(d) { return d[1]; }, 
    xScale = d3.scale.ordinal(), 
    yScale = d3.scale.linear(), 
    yAxis = d3.svg.axis().scale(yScale).orient("left"), 
    xAxis = d3.svg.axis().scale(xScale); 
    var isNegative = false;  

function chart(selection) { 
    selection.each(function(data) { 

    // Convert data to standard representation greedily; 
    // this is needed for nondeterministic accessors. 
    for(var i=0; i< data.length; i++){ 
    if(data[i][1] < 0){ 
     isNegative = true; 
    } 
    } 

    data = data.map(function(d, i) { 
    return [xValue.call(data, d, i), yValue.call(data, d, i)]; 
    }); 

    // Update the x-scale. 
    xScale 
     .domain(data.map(function(d) { return d[0];})) 
     .rangeRoundBands([0, width - margin.left - margin.right], xRoundBands); 


    // Update the y-scale. 
    yScale 
     .domain(d3.extent(data.map(function(d) { return d[1];}))) 
     .range([height - margin.top - margin.bottom, 0]) 
     .nice(); 


    // Select the svg element, if it exists. 
    var svg = d3.select(this).selectAll("svg").data([data]); 

    // Otherwise, create the skeletal chart. 
    var gEnter = svg.enter().append("svg").append("g"); 
    gEnter.append("g").attr("class", "bars"); 
    gEnter.append("g").attr("class", "y axis"); 
    gEnter.append("g").attr("class", "x axis"); 
    gEnter.append("g").attr("class", "x axis zero"); 

    // Update the outer dimensions. 
    svg .attr("width", width) 
     .attr("height", height); 

    // Update the inner dimensions. 
    var g = svg.select("g") 
     .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

// Update the bars. 
    var bar = svg.select(".bars").selectAll(".bar").data(data); 
    bar.enter().append("rect"); 
    bar.exit().remove(); 
    bar .attr("class", function(d, i) { return d[1] < 0 ? "bar negative" : "bar positive"; }) 
     .attr("x", function(d) { return X(d); }) 
     .attr("y", function(d, i) { return d[1] < 0 ? Y0() : Y(d); }) 
     .attr("width", xScale.rangeBand()) 
     .attr("height", function(d, i) { return Math.abs(Y(d) - Y0()); }); 

// x axis at the bottom of the chart 
if(isNegative === true){ 
    var xScaleHeight = height - margin.top - margin.bottom+12; 
}else{ 
    var xScaleHeight = height - margin.top - margin.bottom; 
}   
g.select(".x.axis") 
    .attr("transform", "translate(0," + (xScaleHeight) + ")") 
    .call(xAxis.orient("bottom")) 
    .selectAll("text") 
    .call(wrap, xScale.rangeBand()); 

// zero line 
g.select(".x.axis.zero") 
    .attr("transform", "translate(0," + Y0() + ")") 
    .attr("class", "zero axis") 
    .call(xAxis.tickFormat("").tickSize(0)); 


    // Update the text in bars. 
    var bar1 = svg.select(".bars").selectAll("text").data(data); 

    bar1 .data(data) 
     .enter() 
     .append("text") 
     .attr("class", "text") 
     .text(function(d) { return d[1]+"%"; }) 
     .attr("x", function(d) { return X(d); }) 
     .attr("y", function(d, i) { return d[1] < 0 ? Math.abs(Y(d)+10) : Y(d)-2; }); 

    // Update the y-axis. 
    g.select(".y.axis") 
     //.call(yAxis) 
     .call(yAxis.tickSize(3).ticks(5)) 
     .selectAll("g") 
     .selectAll("text") 
     .text(function(d){ 
      return d+"%"; 
     }); 

    // Horizontal grid 
    g.insert("g", ".bars")   
    .attr("class", "grid horizontal") 

    .call(d3.svg.axis().scale(yScale) 
     .orient("left") 
     .tickSize(-(height), 0, 0) 
     .tickFormat("") 
    ); 
}); 

}

// Custom function for text wrap 
    function wrap(text, width) { 
    text.each(function() { 
    var text = d3.select(this), 
    words = text.text().split(/\s+/).reverse(), 
    word, 
    line = [], 
    lineNumber = 0, 
    lineHeight = 1, // ems 
    y = text.attr("y"), 
    dy = parseFloat(text.attr("dy")), 
    tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em"); 
    while (word = words.pop()) { 
    line.push(word); 
    tspan.text(line.join(" ")); 
    if (tspan.node().getComputedTextLength() > 55) { 
     line.pop(); 
     tspan.text(line.join(" ")); 
     line = [word]; 
     tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word); 
    } 
    } 
}); 
} 


// The x-accessor for the path generator; xScale ∘ xValue. 
function X(d) { 
    return xScale(d[0]); 
} 

function Y0() { 
    return yScale(0); 
} 

// The x-accessor for the path generator; yScale ∘ yValue. 
function Y(d) { 
return yScale(d[1]); 
} 

chart.margin = function(_) { 
    if (!arguments.length) return margin; 
    margin = _; 
    return chart; 
}; 

    chart.width = function(_) { 
    if (!arguments.length) return width; 
    width = _; 
    return chart; 
}; 

chart.height = function(_) { 
    if (!arguments.length) return height; 
    height = _; 
    return chart; 
    }; 

chart.x = function(_) { 
    if (!arguments.length) return xValue; 
    xValue = _; 
    return chart; 
}; 

chart.y = function(_) { 
    if (!arguments.length) return yValue; 
    yValue = _; 
    return chart; 
    }; 

return chart; 
} 

回答

0

你可以做這樣的事情

,而不是你的代碼來生成水平網格

// Horizontal grid 
    g.insert("g", ".bars")   
    .attr("class", "grid horizontal") 

    .call(d3.svg.axis().scale(yScale) 
     .orient("left") 
     .tickSize(-(height), 0, 0) 
     .tickFormat("") 
    ); 
}); 

通過蜱.data(yScale.ticks(5))

g.append("g").selectAll("line.line").data(yScale.ticks(5)).enter() 
.append("line") 
    .attr(
    { 
     "class":"line grid tick", 
     "x1" : margin.right, 
     "x2" : width, 
     "y1" : function(d){ return yScale(d);}, 
     "y2" : function(d){ return yScale(d);}, 
    }); 
}); 

添加這個它會遍歷工作代碼here

+0

請接受的答案,如果有幫助! :) – Cyril

+0

謝謝@Cyril您的回覆,但您可以看到水平網格即將到達酒吧頂部。我希望網格出現在圖表欄後面。我也嘗試了一些CSS屬性,但沒有工作。 :( – MohitAgrawal

+0

檢查這你必須在條形圖之前繪製網格以顯示它http://jsfiddle.net/cyril123/fjuak9bo/3/ – Cyril