2016-06-13 13 views
0

目的:X軸にジョブタイトルが含まれ、Y軸に各ジョブの部品番号が含まれるグリッドを作成します。ジョブが特定の部品番号を複数必要とする場合、セルを垂直方向に2/3/4/5 ...異なるセルに分割しますが、同じ行/列に収まります。複数の色のD3.js矩形を塗りつぶしたり、複数の矩形に分割する

問題:特定のデータポイントに対して複数の矩形を追加する際に問題が発生しています。私はこの答えを使ってみたhereしかし運がなかった。私は幸運もなく各ループのためにaを使ってみました。なにか提案を?

現在の進捗状況:

enter image description here

目標:問題の

enter image description here

コードスニペット:

dayOffset = dayFormat(dateExtent[0]); 
       rect = heatmap.selectAll('rect') 
        .data(data) 
       .enter().append('rect') 
        .attr('width', function (d) { 
         return Xcellscale/d.NumberofPart; 
        }) 
        .attr('height', Ycellscale) 
        .attr('x', function (d) { 
         return xAxisScale(d.JobNumber); 
        }) 
        .attr('y', function (d) { 
         return yAxisScale(d.PartNumber); 
        }) 
        .attr('fill', '#000FF0'); 

JSON:

{ 
     "data": [ 
      { 
       "PartNumber": "a", 
       "JobNumber": "a", 
       "NumberofPart": "2", 
       "timestamp": "2014-09-25T00:00:00", 
       "value": { 
        "PM2.5": 30.22 
       } 
      }, 
      { 
       "PartNumber": "b", 
       "JobNumber": "b", 
       "NumberofPart": "1", 
       "timestamp": "2014-09-25T01:00:00", 
       "value": { 
        "PM2.5": 41.61 
       } 
      }, 
      { 
       "PartNumber": "c", 
       "JobNumber": "c", 
       "NumberofPart": "1", 
       "timestamp": "2014-09-25T02:00:00", 
       "value": { 
        "PM2.5": 50.71 
       } 
      }, 
      { 
       "PartNumber": "d", 
       "JobNumber": "c", 
       "NumberofPart": "1", 
       "timestamp": "2014-09-25T02:00:00", 
       "value": { 
        "PM2.5": 50.71 
       } 
      }, 
      { 
       "PartNumber": "e", 
       "JobNumber": "c", 
       "NumberofPart": "1", 
       "timestamp": "2014-09-25T02:00:00", 
       "value": { 
        "PM2.5": 50.71 
       } 
      }, 
      { 
       "PartNumber": "f", 
       "JobNumber": "c", 
       "NumberofPart": "1", 
       "timestamp": "2014-09-25T02:00:00", 
       "value": { 
        "PM2.5": 50.71 
       } 
      }, 
      { 
       "PartNumber": "g", 
       "JobNumber": "c", 
       "NumberofPart": "1", 
       "timestamp": "2014-09-25T02:00:00", 
       "value": { 
        "PM2.5": 1000.71 
       } 
      }, 
      { 
       "PartNumber": "h", 
       "JobNumber": "c", 
       "NumberofPart": "1", 
       "timestamp": "2014-09-25T03:00:00", 
       "value": { 
        "PM2.5": 250.34 
       } 
      }, 
      { 
       "PartNumber": "i", 
       "JobNumber": "d", 
       "NumberofPart": "1", 
       "timestamp": "2014-09-25T04:00:00", 
       "value": { 
        "PM2.5": 79.64 
       } 
      }, 
      { 
       "PartNumber": "j", 
       "JobNumber": "e", 
       "NumberofPart": "2", 
       "timestamp": "2014-09-25T05:00:00", 
       "value": { 
        "PM2.5": 76.93 
       } 
      }, 
      { 
       "PartNumber": "k", 
       "JobNumber": "f", 
       "NumberofPart": "2", 
       "timestamp": "2014-09-30T06:00:00", 
       "value": { 
        "PM2.5": 106.45 
       } 
      } 
     ] 
    } 

ここに私のコードがあります。このD3.js Exampleに基づいています。タイムスタンプに関して私が削除しなかった余分なコードについては残念です。

$(document).ready(function() { 
    //UI configuration 
    var itemSize = 18, 
     cellSize = itemSize - 1, 
     width = 800, 
     height = 800, 
     margin = { top: 20, right: 20, bottom: 20, left: 25 }; 

    //formats 
    var hourFormat = d3.time.format('%H'), 
     dayFormat = d3.time.format('%j'), 
     timeFormat = d3.time.format('%Y-%m-%dT%X'), 
     monthDayFormat = d3.time.format('%m.%d'); 

    //data vars for rendering 
    var dateExtent = null, 
     data = null, 
     dayOffset = 0, 
     colorCalibration = ['#00ff00', '#0033cc', '#ffcc00', '#ff6600', '#ff0000', '#9E0142'], 
     dailyValueExtent = {}; 

    data = jsondata.data; 

    //axises and scales 
    var axisWidth = 0, 
     axisHeight = itemSize * 24, 
     xAxisScale = d3.scale.ordinal() 
     .domain(data.map(function (d) { return d["JobNumber"]; })) 
     .rangePoints([0, width]); 
    xAxis = d3.svg.axis() 
      .scale(xAxisScale) 
     .orient('top'), 
     yAxisScale = d3.scale.ordinal() 
     .domain(data.map(function (d) { return d["PartNumber"]; })) 
     .rangePoints([0, width]), 
     yAxis = d3.svg.axis() 
     .scale(yAxisScale) 
     .orient('left'); 


    initCalibration(); 

    var svg = d3.select('[role="heatmap"]'); 
    var heatmap = svg 
     .attr('width', width) 
     .attr('height', height) 
    .append('g') 
     .attr('width', width - margin.left - margin.right) 
     .attr('height', height - margin.top - margin.bottom) 
     .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); 
    var rect = null; 


     data.forEach(function (valueObj) { 
      valueObj['date'] = timeFormat.parse(valueObj['timestamp']); 


     }); 

     dateExtent = d3.extent(data, function (d) { 
      return d.date; 
     }); 

     svg.append('g') 
      .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')') 
      .attr('class', 'x axis') 
      .call(xAxis) 
     .append('text') 
      .text('JobNumber') 
      .attr('transform', 'translate(' + axisWidth + ',-10)'); 

     svg.append('g') 
      .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')') 
      .attr('class', 'y axis') 
      .call(yAxis) 
     .append('text') 
      .text('PartNumber') 
      .attr('transform', 'translate(-10,' + axisHeight + ') rotate(-90)'); 

    //render heatmap rects 


     Xcellscale = width/(xAxisScale.domain().length -1); 
     Ycellscale = height/(yAxisScale.domain().length - 1); 

     console.log(Xcellscale + " " + Ycellscale); 
     console.log(width + " " + height); 
     console.log(xAxisScale.domain().length + " " + data.map(function (d) { return d["PartNumber"]; }).length); 

     dayOffset = dayFormat(dateExtent[0]); 
     rect = heatmap.selectAll('rect') 
      .data(data) 
     .enter().append('rect') 
      .attr('width', function (d) { 
       return Xcellscale/d.NumberofPart; 
      }) 
      .attr('height', Ycellscale) 
      .attr('x', function (d) { 
       return xAxisScale(d.JobNumber); 
      }) 
      .attr('y', function (d) { 
       return yAxisScale(d.PartNumber); 
      }) 
      .attr('fill', '#000FF0'); 

     rect.filter(function (d) { return d.value['PM2.5'] > 0; }) 
      .append('title') 
      .text(function (d) { 
       return monthDayFormat(d.date) + ' ' + d.value['PM2.5']; 
      }); 

     //renderColor(); 


    function initCalibration() { 
     d3.select('[role="calibration"] [role="example"]').select('svg') 
      .selectAll('rect').data(colorCalibration).enter() 
     .append('rect') 
      .attr('width', cellSize) 
      .attr('height', cellSize) 
      .attr('x', function (d, i) { 
       return i * itemSize; 
      }) 
      .attr('fill', function (d) { 
       return d; 
      }); 

     //bind click event 
     d3.selectAll('[role="calibration"] [name="displayType"]').on('click', function() { 
      renderColor(); 
     }); 
    } 

    function renderColor() { 
     var renderByCount = document.getElementsByName('displayType')[0].checked; 

     rect 
      .attr('width', function (d) { 
       return Xcellscale/d.NumberofPart; 
      }) 
      .filter(function (d) { 
       return (d.value['PM2.5'] >= 0); 
      }) 
      .transition() 
      .delay(function (d) { 
       return 1; 
      }) 
      .duration(500) 
      .attrTween('fill', function (d, i, a) { 
       //choose color dynamicly  
       var colorIndex = d3.scale.quantize() 
       .range([0, 1, 2, 3, 4, 5]) 
       .domain(([0, 500])); 

       return d3.interpolate(a, '#00ff00'); 
      }) 

    } 

    //extend frame height in `http://bl.ocks.org/` 
    d3.select(self.frameElement).style("height", "600px"); 
}); 
+1

あなたは4つの駅、先頭の1、2、同一途中で停止し、最後に1つずつでてLinearGradient介して2つの色で矩形を埋めることができます。 –

+0

は、linearGradientでストップの量を増やす方法はありますか? – Mark

+1

あなたは望みの数を持つことができ、DOMを直接使うか、またはd3 –

答えて

0

これで分かりました。これはヒートマップ上にデータを取得する最も雄弁な方法ではありませんが、かなりうまく機能します。 selectall()を使うのではなく、data()。enter()私はちょうど私のデータセットを通してforループを使い、そのように矩形を追加しました。私は通常、forループの代わりにマッピング関数を使用する人がいることを知っているので、私がコードを改善することができることが原因で発生する可能性のある問題がある場合は、ここで

は私のコードです:

for (var i = 0; i < data.length; i++) { 

    numberofparts = data[i].NumberofPart; 
    for (var j = 0; j < data[i].NumberofPart; j++) { 

     heatmap.append('rect') 
     .attr('width', Xcellscale/numberofparts) 
     .attr('height', Ycellscale) 
     .attr('x', xAxisScale(data[i].JobNumber) + (j*(Xcellscale/numberofparts))) 
     .attr('y', yAxisScale(data[i].PartNumber)) 
     .attr('fill', function() { 
      if (j == 1) { 
       return '#000FF0'; 
      } 
      else 
       return '#00000' 
     }); 

    } 
} 

そしてここでは、今、私のチャート/ヒートマップのスクリーンショットです:

enter image description here

私は、これは同じことをやろうとしている何人かの人々を助けるかもしれない願っていますもの。私は私がforループを使用して発生する可能性がある問題を回避できますうまくいけば.each()関数を使用して自分のコードを改善し、あなたの助けを借りて、2016年6月16日 おかげでウィルとロバート

UPDATE。私はこの例をbl.ocks.orgから引用して助けました。

私の更新されたコード(私もJSONから変数の束を改称):ここでは

$(document).ready(function() { 
    $.getJSON("/api/?????") 
    .done(function (materialdata) { 

     //UI configuration 
     var itemSize = 18, 
      cellSize = itemSize - 1, 
      width = 2500, 
      height = 15000, 
      margin = { top: 20, right: 20, bottom: 20, left: 100 }; 

     data = materialdata.ChartData; 


     //axises and scales 
     var axisWidth = 0, 
      axisHeight = itemSize * 24, 
      xAxisScale = d3.scale.ordinal() 
      .domain(data.map(function (d) { return d["JobOrderNumber"]; })) 
      .rangePoints([0, width]); 
     xAxis = d3.svg.axis() 
       .scale(xAxisScale) 
      .orient('top'), 
      yAxisScale = d3.scale.ordinal() 
      .domain(materialdata.Domain) 
      .rangePoints([0, height]), 
      yAxis = d3.svg.axis() 
      .scale(yAxisScale) 
      .orient('left'); 

     var svg = d3.select('[role="heatmap"]'); 
     var heatmap = svg 
      .attr('width', width) 
      .attr('height', height) 
     .append('g') 
      .attr('width', width - margin.left - margin.right) 
      .attr('height', height - margin.top - margin.bottom) 
      .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); 
     var rect = null; 

     svg.append('g') 
      .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')') 
      .attr('class', 'x axis') 
      .call(xAxis) 
     .append('text') 
      .text('') 
      .attr('transform', 'translate(' + axisWidth + ',-10)'); 

     svg.append('g') 
      .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')') 
      .attr('class', 'y axis') 
      .call(yAxis) 
     .append('text') 
      .text('') 
      .attr('transform', 'translate(-10,' + axisHeight + ') rotate(-90)'); 

     Xcellscale = (width/(xAxisScale.domain().length - 1)) - 1; 
     Ycellscale = (height/(yAxisScale.domain().length - 1)) - 1; 

     rect = heatmap.selectAll('svg') 
      .data(data) 
     .enter(); 

     rect.append('svg').each(function (d, i) { 
      numberofparts = d.PartQuantity; 
      for (var j = 0; j < d.PartQuantity; j++) { 
       d3.select(this).append('rect') 
       .attr('width', Xcellscale/numberofparts) 
       .attr('height', Ycellscale) 
       .attr('x', xAxisScale(d.JobOrderNumber) + (j * (Xcellscale/numberofparts))) 
       .attr('y', yAxisScale(d.PartNumber)) 
       .attr('fill', function() { 
        return GetPartfromQuantities(materialdata, data[i].PartNumber); 
       }); 
      } 
     }); 

    }); 
}); 

は、それが今どのように見えるかです。私はセットにもっと多くのデータを追加し、配色を加えました。

I added more data an colors to the chart

+1

私は同様の問題に取り組み、 '.each()'を使って成功し、 '.each 'している関数で' d3.select(this) 'を使って成功しました。私はそれを「ネスティング」d3と考えています。あなたのソリューションに対する私の懸念は、 '.data()。enter()'を使用しないと、データをノードにリンクしていないため、後で問題を引き起こす可能性があります。今すぐ完全な解決策を書く時間がありませんが、あなたがまだ興味があるなら教えてください。 – wdickerson

+0

間違いなく、私はあなたが入れ子でそれをする方法を見てみたいと思います。それははるかに優れた戦術のように思え、おそらくもっと木のようなデータセットを扱っているときには役に立ちます。あなたのアイデアは私にとって最高の答えのように聞こえるので、私はしばらくの間、話題を未回答のままにしておきます。また、その間に.each()メソッドをチェックアウトします。 – Mark

+1

私はちょうど役に立つかもしれないMike Bostockによってこの記事を横断しました:https://bost.ocks.org/mike/nest/ – wdickerson

関連する問題