0

学生関連のデータ (以下のサンプル レコード) のデータ ビジュアライゼーションを作成しようとしていますが、d3 でレンダリングすると、データが 2 回処理されて上書きされ、2 回目の結果のみが画面に表示されます。ここでは行カウンターを使用しているため、長方形の数に基づいて各長方形の y 座標を設定する方法があります。そして、これはどういうわけか物事を少し台​​無しにしたと思います。データが 2 回繰り返されないようにする方法についてのヘルプをいただければ幸いです。

また、念のため、このコードは angular.js ディレクティブ内にあります。

ここで本当にばかげたことをしているだけなら申し訳ありません

// student records sample...
var studentData = [
{   
"studentID" : 1001,
"firstName" : "jill",
"lastName" : "smith",
"workLoadDifficulty" : 16,
"smileStartAngle" : -90,
"smileEndAngle" : 90,
},
{   
"studentID" : 1008,
"firstName" : "bob",
"lastName" : "smith",
"workLoadDifficulty" : 99,
"smileStartAngle" : 90,
"smileEndAngle" : -90,
}
];
(function () {
'use strict';
angular.module('learnerApp.directives')
.directive('d3Bars', ['d3', function(d3) {
  return {
    restrict: 'EA',
    scope: {
      data: "=",
      label: "@",
      onClick: "&"
    },
    link: function(scope, iElement, iAttrs) {
      var paddingForShape = 10;
      var rowCounter = -1;
      var height = 400;
      var width = 300;
      var svgContainer = d3.select(iElement[0])
          .append("svg")
          .attr("width", width)
          .attr('height', height);

      // on window resize, re-render d3 canvas
      window.onresize = function() {
        return scope.$apply();
      };
      scope.$watch(function(){
          return angular.element(window)[0].innerWidth;
        }, function(){
          return scope.render(scope.data);
        }
      );

      // watch for data changes and re-render
    scope.$watch('studentData', function(newVals, oldVals) {
        return scope.render(newVals);
      }, true); 

      // define render function
      scope.render = function(data){
        // remove all previous items before render
      svgContainer.selectAll("*").remove();

      var workLoadColor = d3.scale.category10()
            .domain([0,100])
            .range(['#02FA28', '#73FA87', '#C0FAC9','#FAE4C0', '#FAC775', '#FAA823','#FA9A00','#FA8288', '#FC4750', '#FA0511' ])


   var studentRects = svgContainer.selectAll('rect')
      .data(studentData, function(d) { 
        console.log(d.studentID);
        console.log('hello');
        return "keyVal" + d.studentID;
         })
      .enter()
        .append("rect");

      var studentRectAttributes = studentRects
                .attr("x", function(d,i) {
                    return ((i * 50) % width) + paddingForShape;
                })
                .attr("y", function(d,i) {
                    var value = ((i * 50) % width)
                    if (value === 0) {
                      rowCounter = rowCounter + 1;
                    }                    
                    var value = (rowCounter * 50);
                    console.log('Y Val: ', i);
                    console.log(value);
                    return value;
                })                   
                .attr("height", 30)
                .attr("width", 40)
                .style("fill", function(d) {
                  return workLoadColor(d.workLoadDifficulty)
                });


      };
    }
  };
}]);
}());
4

2 に答える 2

1

データ結合を 2 回実行する場合はkey、現在選択している要素を上書きしないように、を指定する必要があります。studentRects定義を次のように変更できます。

var studentRects = svgContainer.selectAll('rect')
  .data(studentData, function(d) { return d.firstName + ' ' + d.lastName; });
studentRects.enter().append("rect");

見るselection.data([values[, key]])

キー機能が指定されていない場合、指定された配列の最初のデータムは現在の選択の最初の要素に割り当てられ、2 番目のデータムは 2 番目に選択された要素に割り当てられます。

于 2013-10-28T04:24:51.893 に答える
1

追加する要素var studentRects = svgContainer.selectAll('rect')に一致するセレクターを変更してみてください<rect>enter()

** 更新しました **

@Wex が提供した重要なアドバイスに加えて、コードを plunker に書き込んで動作させました。スコープに余分な時計があり、それを削除すると問題が解決します(ただし、入力/終了に関する d3 ドキュメントのいくつかを再確認することをお勧めします)。

  scope.$watch(function(){
      return angular.element(window)[0].innerWidth;
  }, function(){
      return scope.render(scope.data);
  });

プランカーはこちら: http://plnkr.co/edit/z0MXkUVFNmMEGJAaz7dw?p=preview

于 2013-10-28T03:40:47.800 に答える