2017-10-19 90 views
1

我一直在这个小时,似乎无法让我的分组条形图表现。特别是试图为每个栏周围的'g'翻译属性获取适当的宽度。d3响应条形图

我已经尝试了多种方法,这似乎是最优雅的,虽然我打开其他解决方案。我们的目标是这样的:http://www.cagrimmett.com/til/2016/04/26/responsive-d3-bar-chart.html

var data = [{"category":"Securily Provisions","values":[{"value":50,"rate":"Work Performed"},{"value":40,"rate":"Knowledge, Skills, and Abilities"}]},{"category":"Investigate","values":[{"value":25,"rate":"Work Performed"},{"value":21,"rate":"Knowledge, Skills, and Abilities"}]},{"category":"Operate and Maintain","values":[{"value":3,"rate":"Work Performed"},{"value":22,"rate":"Knowledge, Skills, and Abilities"}]},{"category":"Oversee and Govern","values":[{"value":12,"rate":"Work Performed"},{"value":7,"rate":"Knowledge, Skills, and Abilities"}]},{"category":"Protect and Defend","values":[{"value":6,"rate":"Work Performed"},{"value":15,"rate":"Knowledge, Skills, and Abilities"}]},{"category":"Collect and Operate","values":[{"value":92,"rate":"Work Performed"},{"value":85,"rate":"Knowledge, Skills, and Abilities"}]}] 
 

 
var margin = {top: 20, right: 20, bottom: 30, left: 40}, 
 
    width = 960 - margin.left - margin.right, 
 
    height = 500 ; 
 

 
var x0 = d3.scale.ordinal().rangeRoundBands([0, width], .5); 
 

 
var x1 = d3.scale.ordinal(); 
 

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

 
var xAxis = d3.svg.axis() 
 
    .scale(x0) 
 
    .orient("bottom"); 
 

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

 
var color = d3.scale.ordinal() 
 
    .range(["#02bfe7","#fdb81e"]); 
 

 
var svg = d3.select('#chart-area').append("svg") 
 
    .attr("width", width + margin.left + margin.right) 
 
    .attr("height", height + margin.top + margin.bottom) 
 
    .attr("preserveAspectRatio", "xMinYMin meet") 
 
    .append("g").attr("class","container") 
 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 
 

 
//d3.json("data.json", function(error, data) { 
 

 
    var categoriesNames = data.map(function(d) { 
 
    return d.category; 
 
    }); 
 

 
    var rateNames = data[0].values.map(function(d) { 
 
    return d.rate; 
 
    }); 
 

 
    x0.domain(categoriesNames); 
 
    x1.domain(rateNames).rangeRoundBands([0, x0.rangeBand()]); 
 

 
    y.domain([0, d3.max(data, function(categorie) { 
 
    return d3.max(categorie.values, function(d) { 
 
     return d.value; 
 
    }); 
 
    })]); 
 

 
    svg.append("g") 
 
    .attr("class", "x axis") 
 
    .attr("transform", "translate(0," + height + ")") 
 
    .call(xAxis); 
 

 
    svg.append("g") 
 
    .attr("class", "y axis") 
 
    .style('opacity','0') 
 
    .call(yAxis) 
 
    .append("text") 
 
    .attr("transform", "rotate(-90)") 
 
    .attr("y", 6) 
 
    .attr("dy", ".71em") 
 
    .style("text-anchor", "end") 
 
    .style('font-weight','bold') 
 
    .text("Value"); 
 

 
    svg.select('.y').transition().duration(500).delay(1300).style('opacity','1'); 
 

 
    var slice = svg.selectAll(".slice") 
 
    .data(data) 
 
    .enter().append("g") 
 
    .attr("class", "g") 
 
    .attr("transform",function(d) { return "translate(" + x0(d.category) + ",0)"; }); 
 

 
    slice.selectAll("rect") 
 
    .data(function(d) { return d.values; }) 
 
    .enter().append("rect") 
 
    .attr("width", x1.rangeBand()) 
 
    .attr("x", function(d) { return x1(d.rate); }) 
 
    .style("fill", function(d) { return color(d.rate) }) 
 
    .attr("y", function(d) { return y(0); }) 
 
    .attr("height", function(d) { return height - y(0); }) 
 
    .on("mouseover", function(d) { 
 
     d3.select(this).style("fill", d3.rgb(color(d.rate)).darker(2)); 
 
    }) 
 
    .on("mouseout", function(d) { 
 
     d3.select(this).style("fill", color(d.rate)); 
 
    }); 
 

 
    slice.selectAll("rect") 
 
    .transition() 
 
    .delay(function (d) {return Math.random()*1000;}) 
 
    .duration(1000) 
 
    .attr("class","bar") 
 
    .attr("y", function(d) { return y(d.value); }) 
 
    .attr("height", function(d) { return height - y(d.value); }); 
 

 
    //Legend 
 
    var legend = svg.selectAll(".legend") 
 
    .data(data[0].values.map(function(d) { return d.rate; }).reverse()) 
 
    .enter().append("g") 
 
    .attr("class", "legend") 
 
    .attr("transform", function(d,i) { return "translate(0," + i * 20 + ")"; }) 
 
    .style("opacity","0"); 
 

 
    legend.append("rect") 
 
    .attr("x", width - 18) 
 
    .attr("width", 18) 
 
    .attr("height", 18) 
 
    .style("fill", function(d) { return color(d); }); 
 

 
    legend.append("text") 
 
    .attr("x", width - 24) 
 
    .attr("y", 9) 
 
    .attr("dy", ".35em") 
 
    .style("text-anchor", "end") 
 
    .text(function(d) {return d; }); 
 

 
    legend.transition().duration(500).delay(function(d,i){ return 1300 + 100 * i; }).style("opacity","1"); 
 

 
    document.addEventListener("DOMContentLoaded", resize); 
 
    d3.select(window).on('resize', resize); 
 

 
    function resize() { 
 
    console.log('----resize function----'); 
 
    // update width 
 
    width = parseInt(d3.select('#chart-area').style('width'), 10); 
 
    width = width - margin.left - margin.right; 
 

 
    height = parseInt(d3.select("#chart-area").style("height")); 
 
    height = height - margin.top - margin.bottom; 
 
    console.log('----resiz width----'+width); 
 
    console.log('----resiz height----'+height); 
 
    // resize the chart 
 

 
    x0.range([0, width]); 
 
    x0.rangeRoundBands([0, width], .03); 
 
    y.range([height, 0]); 
 

 
    yAxis.ticks(Math.max(height/50, 2)); 
 
    xAxis.ticks(Math.max(width/50, 2)); 
 

 
    d3.select(svg.node().parentNode) 
 
     .style('width', (width + margin.left + margin.right) + 'px'); 
 

 
    svg.selectAll('.g') 
 
     //.attr("x", function(d) { return x0(categoriesNames); }) 
 
     //.attr("x", function(d) { return x1(d.rate); }) 
 
     // Problem here applying new width within translate 
 
     .attr("transform", "translate(10,0)") 
 
     .attr("width", x1.rangeBand()); 
 

 
    svg.selectAll("text") 
 
     // .attr("x", function(d) { return x0(categoriesNames); }) 
 
     .attr("x", (function(d) { return x0(categoriesNames \t) + x0.rangeBand()/2 ; } )) 
 
     .attr("y", function(d) { return y(rateNames) + 1; }) 
 
     .attr("dy", ".75em"); 
 

 
    svg.select('.x.axis').call(xAxis.orient('bottom')).selectAll("text").attr("x",55); 
 

 

 
    } 
 
//});
.bar{ 
 
     fill: steelblue; 
 
    } 
 

 
    .bar:hover{ 
 
     fill: brown; 
 
    } 
 

 
    .axis { 
 
     font: 10px sans-serif; 
 
    } 
 

 
    .axis path, 
 
    .axis line { 
 
     fill: none; 
 
     stroke: #000; 
 
     shape-rendering: crispEdges; 
 
    } 
 
    #chart-area {width: 100%;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 
 

 
<div id="chart-area"></div>

回答

0

这里有一个解决方案。这是期望的输出吗?尝试调整窗口的大小。

JS FIDDLE

大小功能:

function resize() { 
console.log('----resize function----'); 
// update width 
width = parseInt(d3.select('#chart-area').style('width'), 10); 
width = width - margin.left - margin.right; 

height = parseInt(d3.select("#chart-area").style("height")); 
height = height - margin.top - margin.bottom; 
console.log('----resiz width----'+width); 
console.log('----resiz height----'+height); 
// resize the chart 

    x0.rangeRoundBands([0, width], .5); 
x1.domain(rateNames).rangeRoundBands([0, x0.rangeBand()]); 
y.range([height, 0]); 

yAxis.ticks(Math.max(height/50, 2)); 
xAxis.ticks(Math.max(width/50, 2)); 

d3.select(svg.node().parentNode) 
    .style('width', (width + margin.left + margin.right) + 'px'); 

svg.selectAll('.g') 
    .attr("transform",function(d) { 
    return "translate(" + x0(d.category) + ",0)"; 
    }); 
    svg.selectAll('.g').selectAll("rect").attr("width", x1.rangeBand()) 
    .attr("x", function(d) { return x1(d.rate); }) 
svg.selectAll(".legend rect") 
    .attr("x", width - 18); 
svg.selectAll('.legend text') 
    .attr("x", width - 24) 
svg.select('.x.axis').call(xAxis.orient('bottom')); 
} 

我做出了调整大小功能的一些变化。这里的原因:

x0.rangeRoundBands([0,width],.5); 
x1.domain(rateNames).rangeRoundBands([0,x0.rangeBand()]); 
y.range([height, 0]); 
  • 翻译的(10,0)正在力大小调整功能设置和:

    1. X0和X1的范围(两者)都对调整大小重置您无法将宽度应用于(组)。 基本上,你只需要调用原始渲染中包含宽度和高度变化的所有代码。看看调整大小功能。

    2. 重新绘制X轴在底部包括对x的静态值蜱:

    svg.select('.x.axis').call(xAxis.orient('bottom')).selectAll("text").attr("x",55);

    只是删除了attr("x", 55)

    希望这有助于。 :)