2016-09-30 77 views
0

我創建了一個水平條形圖。d3js:根據變量使用if條件爲每個條添加多種顏色

每個條的寬度基於對象變量。後來才知道我需要使每個條形疊層條代替,所述2類對象變量是VOL1 & VOL2,其中VOL1 + VOL2 = 體積

我想知道是否有基於VOL1 & VOL2值而不是通常的堆疊棒法每個杆分配2色直接的方式在需要的(a)安排數據在基於其類別的陣列中,(b)定義x,y,y0(c)爲每個陣列條分配不同的顏色。

數據結構:

var data = [ 
{ "merchant": "A", 
    "volume": 100, 
    "vol1": 48, 
    "vol2": 52 
}, 
{...}, 
{...} 
]; 

的特定的代碼來繪製圖表是:

var bar = d3.select(".mainGroup").selectAll(".bar") 
      .data(data_merchantTop100Vol); 

    bar.attr("x", 0) 
     .attr("y", d => y(d.merchant)) 
     .attr("height", y.rangeBand()) 
     .transition().duration(50) 
     .attr("width", d => x(d.volume)); 

    bar.enter().append("rect") 
     .attr("class", "bar") 
     .attr("x", 0) 
     .attr("y", d => y(d.merchant)) 
     .attr("height", y.rangeBand()) 
     .transition().duration(50) 
     .attr("width", d => x(d.volume)) 
     // THIS PART IS TO FILL 2 COLORS TO THE 2 SECTIONS OF EACH BAR 
     // .style("fill", function(d) { 
     //  if(d.Vol1) { return "blue"} 
     //  else if (d.vol2) { return "red"}; 
     // }) 

總之,我想的典型使用,如果條件着色方法以創建水平堆疊巴,而不是堆疊條形法。理念的靈感:http://www.d3noob.org/2013/01/select-items-with-if-statement-in-d3js.html

當前水平條形圖:
enter image description here

期望的結果:
enter image description here

+0

所以,你想用一個基於價值的百分比'vol1'和'vol2'填補了單'rect'就結了?或者你想要兩個'rect',每個條被填充到一個顏色? – Mark

+0

一個單一的'rect',根據'vol1'和'vol2'值的百分比填充。如果我有2個'rect',它將是典型的堆棧條方法。 :) – Shawn

+0

這是可行的,如果你真的想要它,但@mpbastos是正確的。使用兩個rects更簡單。 – Mark

回答

2

你可以嘗試使用正確的百分比與gradients填補了矩形,但是這將解決在複雜。最簡單的方法是爲每種顏色使用一個矩形。你並不需要重新排列的數據是:

// Vol1 bars 
    bar.enter().append("rect") 
     .attr("class", "bar") 
     .attr("x", 0) 
     .attr("y", d => y(d.merchant)) 
     .attr("height", y.bandwidth()) 
     .transition().duration(50) 
     .attr("width", d => x(d.vol1)) 
    .style("fill", "blue") 

// Vol2 bars 
    bar.enter().append("rect") 
     .attr("class", "bar") 
     .attr("x", d => x(d.vol1)) 
     .attr("y", d => y(d.merchant)) 
     .attr("height", y.bandwidth()) 
     .transition().duration(50) 
     .attr("width", d => x(d.vol2)) 
    .style("fill", "red") 
+0

謝謝,工作解決方案:) – Shawn

1

如果你真的想用一個單杆做到這一點,你必須設置一個可以在一個個分割的顏色定製梯度:

<!DOCTYPE html> 
 
<html> 
 

 
<head> 
 
    <script data-require="[email protected]" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script> 
 
</head> 
 

 
<body> 
 

 
    <script> 
 
    var data = [{ 
 
     volume: Math.random() * 400, 
 
     vol1: Math.random() * 400, 
 
     vol2: Math.random() * 400 
 
    }, { 
 
     volume: Math.random() * 400, 
 
     vol1: Math.random() * 400, 
 
     vol2: Math.random() * 400 
 
    }, { 
 
     volume: Math.random() * 400, 
 
     vol1: Math.random() * 400, 
 
     vol2: Math.random() * 400 
 
    }, { 
 
     volume: Math.random() * 400, 
 
     vol1: Math.random() * 400, 
 
     vol2: Math.random() * 400 
 
    }]; 
 

 
    var height = 400, 
 
     width = 600, 
 
     color1 = "orange", 
 
     color2 = "steelblue", 
 
     barHeight = 20; 
 

 
    var svg = d3.select('body') 
 
     .append('svg') 
 
     .attr('width', width) 
 
     .attr('height', height); 
 

 
    var defs = svg.append("defs"); 
 

 
    var g = svg.selectAll("g") 
 
     .data(data) 
 
     .enter() 
 
     .append("g") 
 

 
    g.append("rect") 
 
     .attr("width", function(d) { 
 
     return d.volume 
 
     }) 
 
     .attr("height", barHeight) 
 
     .attr("x", 10) 
 
     .attr("y", function(d, i) { 
 
     return i * (barHeight + 5); 
 
     }) 
 
     .style("fill", function(d, i) { 
 

 
     var p = (d.vol1/(d.vol1 + d.vol2)) * 100, 
 
      grad = defs.append("linearGradient") 
 
      .attr("id", "grad_" + i); 
 

 
     grad.append("stop") 
 
      .attr("offset", "0%") 
 
      .attr("stop-color", color1); 
 
     grad.append("stop") 
 
      .attr("offset", (p) + "%") 
 
      .attr("stop-color", color1); 
 
     grad.append("stop") 
 
      .attr("offset", (p) + "%") 
 
      .attr("stop-color", color2); 
 
     grad.append("stop") 
 
      .attr("offset", "100%") 
 
      .attr("stop-color", color2); 
 

 
     return "url(#grad_" + i + ")"; 
 
     }); 
 
     
 
    g.append("text") 
 
     .attr("x", function(d) { 
 
     return d.volume + 12 
 
     }) 
 
     .attr("y", function(d, i) { 
 
     return (i * (barHeight + 5)) + 13; 
 
     }) 
 
     .text(function(d){ 
 
     var p1 = (d.vol1/(d.vol1 + d.vol2)) * 100, 
 
      p2 = (d.vol2/(d.vol1 + d.vol2)) * 100; 
 
     
 
     return Math.round(p1) + "% and " + Math.round(p2) + "%"; 
 
     }) 
 
     .style("stroke", "none") 
 
     .style("fill", "black") 
 
     .style("font-family", "arial") 
 
     .style("font-size", "12px"); 
 
    </script> 
 

 
</body> 
 

 
</html>

+0

謝謝!我會分析和理解你的代碼 – Shawn