var data; d3.csv("data.csv",function(err,d) { data = {}; d.forEach(function(d) { var kyn = d.kyn, aldur = +d.aldur; Object.keys(d) .filter(function(d) { return d != 'kyn' && d != 'aldur';}) .forEach(function(e,i) { var born = +e-aldur; var elem = data[kyn+born] = data[kyn+born] || {kyn:kyn,born:born,domain:[],range:[]}; // Data is in order, so we can simply push elem.domain.push(e); elem.range.push(d[e]); }); }); data = d3.values(data); // Create scales for each sex + birth_year data.forEach(function(d) { d.values = d3.scale.linear() .domain(d.domain) .range(d.range); }); // Create a rectangle for each group bars.selectAll("rect") .data(data) .enter() .append("rect") .attr({height:20,x:0}) .attr("class",function(d) { return d.kyn;}); redraw(slide.value); }); var margin = 100, height = 600, width = 900/2; svgheight = 500; svgymargin = -25; var svg = d3.select("svg") .attr({width:2*width,height:svgheight}); var title = svg.append("text") .attr({class:"title",x:width,y:20}) .style("text-anchor","middle"); var y = d3.scale.linear() .domain([0,90]) .range([height-margin,margin]); // Define separate scales for both sexes var scales = { kk: d3.scale.linear() .domain([0,80000]) .range([width,margin]), kvk: d3.scale.linear() .domain([0,80000]) .range([width,2*width-margin]) }; ['男','女'].forEach(function(kyn) { var dd = 'kvk'; if(kyn == '男'){ dd = 'kk'; } svg.append("text") .attr({class:"title",x:scales[dd](80000/2),y:55}) .text(kyn); }); var bars = svg.append("svg") .attr({x:0,y:svgymargin,height:height-margin,width:2*width}); // Y axes // We draw y-scale twice, first one is a white thick strokes for text labels svg.append("g").attr("class","y axis white") .attr("transform","translate("+(width)+","+(svgymargin)+")") .call(d3.svg.axis().scale(y).orient("left")); svg.append("g").attr("class","y axis") .attr("transform","translate("+(width)+","+(svgymargin)+")") .call(d3.svg.axis().scale(y).orient("left")); d3.selectAll(".y.axis") .call(function(g) { g.selectAll("text").attr("dx",17);}) .selectAll(".tick.major").selectAll("line").remove(); // X axes svg.append("g").attr("class","kk axis") .attr("transform","translate(0,"+(height-margin+svgymargin)+")") .call(d3.svg.axis().scale(scales['kk']).orient("bottom").ticks(5)); svg.append("g").attr("class","kvk axis") .attr("transform","translate(0,"+(height-margin+svgymargin)+")") .call(d3.svg.axis().scale(scales['kvk']).orient("bottom").ticks(5)); function redraw(year) { if (!data) return; title.text("人口ピラミッド(青森県) ("+Math.round(year)+")"); bars.selectAll("rect") // The scale used is determined by sex (i.e. d.kyn). We use min and abs to ensure // the left corner and width is correct for both .attr("x",function(d) { return Math.min(scales[d.kyn](0),scales[d.kyn](d.values(year))||0 ); }) .attr("width",function(d) { return Math.abs(scales[d.kyn](0) - scales[d.kyn](d.values(year))||0); }) .attr("y",function(d) { return y(year-d.born);}); }