2016-11-10 10 views
2

以下のコードは、 'data'というオブジェクトの配列内に単一の値の棒グラフを作成します。データのコレクションを使用して積み上げ棒グラフを作成するにはどうすればよいですか?私はバーの高さは炭水化物の値の合計、脂肪、タンパク質が、それぞれの値と一緒にいたいマージンd3.jsオブジェクト内の値から積み上げ棒グラフを作成する

var w = 700; 
var h = 500; 
var margin = { 
    top: 58, 
bottom: 120, 
    left: 60, 
    right: 40 
}; 
var width = w - margin.left - margin.right; 
var height = h - margin.top - margin.bottom; 

data =[ 
{ name: "Subway", carbs: "480", fat: "400", protein: "120", sum: "1000"}, 
{ name: "Steak & Potatos", carbs: "900", fat: "350", protein: "200", sum: "1450"}, 
{ name: "Sausage", carbs: "50", fat: "350", protein: "80", sum: "480"} 
]; 

データを定義する設定

別の色にすること。 を定義するx

var x = d3.scale.ordinal() 
    .domain(data.map(function(e){ 
     return e.name; 
    })) 
    .rangeBands([0,width]); 

を定義します。これは私が助けを必要と思うところです

var y = d3.scale.linear() 
    .domain([0, d3.max(data, function(d,i){ 

     return parseInt(d.carbs) ; 
    })]) 
    .range([height, 0]); 

上記は私に単一の値(炭水化物)の棒を与えます。しかし、私が本当にやりたいことは、積み重ね棒グラフを作成することです。どんな助けでも大歓迎です。

を追加しました以下の投稿を答えた後

var z = d3.scale.ordinal() 
.range(["#ff0", "#f00", "#0ff"]) 
.domain(["carbs", "fat", "protein"]); 

これは私

function plot(params){ 

    this.append('g') 
    .call(params.gridlines) 
    .classed('gridline', true) 
    .attr('transform','translate(0,0)'); 

    this.selectAll('bar') 
    .data(params.data) 
    .enter() 
    .append('rect') 
    .classed('bar', true) 
    .attr('x', function(d,i){ 
     return x(d.name) 
    }) 
    .attr('y',function(d,i){ 
     return y(d.carbs); 
    }) 
    .attr('width', function(d){ 
     return x.rangeBand(); 
    }) 
    .attr('height', function(d,i){ 
     return height - y(d.carbs) 
    }) 
    .style('fill',function(d,i){ 
     return ordinal_color_scale(i); 
    }); 

this.selectAll('.bar_label') 
     .data(params.data) 
     .enter() 
      .append('text') 
      .classed('bar_label', true) 
      .attr('x', function(d,i){ 
       return x(d.name) + (x.rangeBand()/2); 
      }) 
      .attr('dx', 0) 
      .attr('y', function(d,i){ 
        return y(d.carbs); 
       }) 
      .attr('dy', -6) 
      .text(function(d){ 
       return d.carbs; 
      }); 

     this.append('g') 
      .classed('x axis', true) 
      .style('fill', '#ffd000') 
      .attr('transform','translate('+ 0 +','+ height +')') 
      .call(params.axis.x) 
       .selectAll('text') 
       .style('text-anchor','end') 
       .attr('dx', -8) 
       .attr('dy',8) 
       .attr('transform','translate(0,0) rotate(-45)'); 

     this.append('g') 
      .classed('y axis', true) 
      .style('fill', '#ffd000') 
      .attr('transform','translate(0,0)') 
      .call(params.axis.y); 
} 

plot.call(chart, { 
    data: data, 
    axis: { 
     x: x_axis, 
     y: y_axis 
    }, 
    gridlines: y_gridlines 
}); 

チャートを描画する関数plotは「zはあなたの矩形がどのように見えるかを決定しますここにあなたのカラースケールです」理解できないのは、グラフ上のバーにz変数を描画する方法です。

答えて

0

あなたのドメインは本当に間違っています。範囲は、単にカーボだけでなく、すべての変数を考慮する必要があります。つまり、あなたのmax関数はすべてのプロパティの合計を考慮する必要があります。

(それは積み重ね棒グラフだから)最後に、あなたのバーがすべてのあなたの特性の合計と高くなり、これは
var y = d3.scale.linear() 
    .domain([0, d3.max(data, function(d,i){ 
     return parseInt(d.sum); 
})]) 
.range([height, 0]); 

その後、ときstack機能を使用する必要があります実際には<rect>要素を描画します。各バーは、あなたはそのための任意のコードを投稿しませんでしたが、それは最も可能性が高いようになります(一方を他方の上に積み重ねられた炭水化物のための1、脂肪とタンパク質)3つの<rect>の要素が含まれます:

// z is your color scale here which will decide what your rectangles look like 
var z = d3.scaleOrdinal() 
    .range(["#<colorForCarbs>", "#<colorForFat>", "#<colorForProtein>"]) 
    .domain(["carbs", "fat", "protein"]); 

g.selectAll(".serie") 
.data(stack.keys(["carbs", "fat", "protein"])(data)) 
.enter().append("g") 
    .attr("class", "serie") 
    .attr("fill", function(d) { return z(d.key); }) 
.selectAll("rect") 
.data(function(d) { return d; }) 
.enter().append("rect") 
    .attr(class, 'bar') 
    .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()); 

A「セリエこの例では、例えば、「炭水化物」に関連するすべての矩形(炭水化物、脂肪およびタンパク質の3つの長方形を含むスタックとは対照的に)である。あなたが何か欠けている場合

この例では、あなたが必要なすべてを与える必要があります:あなたの更新質問でhttp://bl.ocks.org/mbostock/3886208

EDIT

を、これはあなたがzのスケールを使用しなければならないコードのセクションですその代わりの

this.selectAll('bar') 
    .data(params.data) 
    .enter() 
    .append('rect') 
    .classed('bar', true) 
    .attr('x', function(d,i){ 
     return x(d.name) 
    }) 
    .attr('y',function(d,i){ 
     return y(d.carbs); 
    }) 
    .attr('width', function(d){ 
     return x.rangeBand(); 
    }) 
    .attr('height', function(d,i){ 
     return height - y(d.carbs) 
    }) 
    .style('fill',function(d,i){ 
     return ordinal_color_scale(i); 
    }); 

var stack = d3.stack(); 
g.selectAll(".serie") 
    .data(stack.keys(["carbs", "fat", "protein"])(data)) 
    .enter().append("g") 
    .attr("class", "serie") 
    .attr("fill", function(d) { return z(d.key); }) 
    .selectAll("rect") 
     .data(function(d) { return d; }) 
     .enter() 
     .append("rect") 
      .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.rangeBand()); 
01を使用
+0

scaleOrdinalがこのエラーを受けていたため、z変数にscale.ordinalを変更しました。 'Uncaught TypeError:d3.scaleOrdinalは関数ではありません(...)'。 あなたが私に与えたリンクされた例のコードをコピーしたことに注目したいと思います。コードはd3ライブラリで動作しましたが、私のライブラリのものでは動作しませんでした。それは厄介です! – Derreck

+0

これは、d3 v3(および私のコードはd3 v4を使用)を使用しているためです。本当に多くを変えるべきではありません。私の編集を参照してください –

+0

私はd3 v4を使用し、scaleOrdinalにscale.ordinalを切り替えると、「d3.scaleOrdinal(...)。domain(...)」というエラーが表示されます。rangeBandsは関数(...)ではありません。私はどんどん近くになっていますか? – Derreck

関連する問題