2017-09-10 79 views
1

我正在繪製帶有座標軸的條形圖,而yScale在我的yAxis上的行爲與我的附加條上的行爲不同。yScale不一致行事d3.js

我將我的yScale範圍設置爲從(h - yPadding)開始,爲xAxis標籤留出底部的額外空間。

   var yScale = d3.scale.linear() 
          .domain([0, d3.max(val)]) 
          .range([h - yPadding, 0]); 

- 範圍反轉,否則我的y軸標籤是顛倒的。

當我使用yScale調用yAxis時,它遵循(h - yPadding)的起點並將空間留在底部。

但是我追加到圖表的所有「rects」,從h開始,而不是(h - yPadding),即使我在這些「rects」上調用yScale就像在yAxis上一樣。

如果我將範圍更改爲[h,0]而不是[h - yPadding,0],則只有yAxis對更改作出反應,條形圖仍以h開頭。

爲什麼欄忽略yScale?

<script type="text/javascript"> 
     var xhr = new XMLHttpRequest(); 

     function makeRequest(){ 
      xhr.open("GET", "https://api.coinmarketcap.com/v1/ticker/", true); 
      xhr.send(); 
      xhr.onreadystatechange = processRequest; 
     } 

     function processRequest(){ 
      console.log("testing, state: ", xhr.readyState) 
      if(xhr.readyState == 4 && xhr.status == 200){ 
       dataset = []; 
       for(var i = 0; i < 10; i++){ 
        addingId = JSON.parse(xhr.responseText)[i]; 
        addingId.id = i; 
        dataset.push(addingId); 
       } 
       console.log("this is dataset: ", dataset); 
       makeChart(); 
      } 
     } 

     function makeChart(){ 
      var w = 1000; 
      var h = 600; 
      var padding = 40; 
      var yPadding = 80; 

      var val = []; 
      dataset.forEach(function(ele){ 
       val.push(parseInt(ele.market_cap_usd)); 
      }) 
      var max = d3.max(val) 

      var xAxisNames = [] 

      dataset.forEach(function(ele){ xAxisNames.push(ele.name); }) 
      // console.log(">>>>>>>>", xAxisNames) 

      var xScale = d3.scale.ordinal() 
          .domain(d3.range(dataset.length)) 
          .rangeRoundBands([padding, w - padding], 0.05) 

      var yScale = d3.scale.linear() 
          .domain([0, d3.max(val)]) 
          .range([h - yPadding, 0]); 

      var yAxis = d3.svg.axis() 
          .scale(yScale) 
          .orient("left") 
          .tickFormat(function(d){ 
           if(d > 0){ return d/1000000000 + " b"; } 
           return ""; 
          }) 

      var xAxis = d3.svg.axis() 
          .scale(xScale) 
          .orient("bottom") 
          .tickFormat(function(d, i){ 
           return xAxisNames[i] 
          }) 

      var svg = d3.select("body") 
         .append("svg") 
         .attr("width", w) 
         .attr("height", h); 

      svg.selectAll("rect") 
       .data(dataset) 
       .enter() 
       .append("rect") 
       .attr("x", function(d, i){ 
        return xScale(i); 
       }) 
       .attr("y", function(d){ 
        return yScale(d.market_cap_usd); 
       }) 
       .attr("width", xScale.rangeBand()) 
       .attr("height", function(d, i){ 
        return h - yScale(d.market_cap_usd) 
       }) 

      svg.append("g") 
       .attr("class", "y axis") 
       .attr("transform", "translate(" + padding + ", 0)") 
       .call(yAxis); 

      svg.append("g") 
       .attr("class", "x axis") 
       .attr("transform", "translate(0, " + (h - yPadding) + ")") 
       .call(xAxis) 
       .selectAll("text") 
       .attr("y", 15) 
       .attr("font-size", 12) 
       .attr("x", xScale.rangeBand()/2) 
       .attr("transform", "rotate(45)") 
     } 

     makeRequest(); 

    </script> 

回答

1

一個比例尺只是將輸入域映射到輸出範圍,僅此而已。您必須相應地設置SVG元素的位置和尺寸。讓我們來看看:

眼下,鑑於你的規模,當你通過它在你的域最小值則回覆:

h - yPadding 

你想具有零個像素的高度,酒吧,當然。爲了得到這個零,方程很簡單,你必須從該值中減去:

(h - yPadding) - yScale(minimumDomainValue) 

這會給你零的最小值在域中。

因此,這應該是矩形的高度:

.attr("height", function(d, i){ 
    return (h - yPadding) - yScale(d.market_cap_usd) 
}) 

PS:順便說一下,在D3,這裏的比例決定了少數情況之一的SVG元素的尺寸是由軸生成器創建的路徑/線。這就是爲什麼你在軸上看到不同的行爲。

+0

好的,我明白你在說什麼,謝謝!我認爲(h - yPadding)會混亂酒吧的規模,但它只是設置酒吧停止x/y座標。偉大的工程! – iggirex