Angular Directive $观看没有回复

时间:2015-12-05 00:19:28

标签: javascript angularjs d3.js svg

我正在尝试使用d3和角度。我已经设置了以下d3模块:

angular.module('DTBS.d3', [])
  .factory('d3Service', ['$document', '$q', '$rootScope',
    function($document, $q, $rootScope) {
      var d = $q.defer();
      function onScriptLoad() {
        // Load client in the browser
        $rootScope.$apply(function() { d.resolve(window.d3); });
      }
      // Create a script tag with d3 as the source
      // and call our onScriptLoad callback when it
      // has been loaded
      var scriptTag = $document[0].createElement('script');
      scriptTag.type = 'text/javascript'; 
      scriptTag.async = true;
      scriptTag.src = 'http://d3js.org/d3.v3.min.js';
      scriptTag.onreadystatechange = function () {
        if (this.readyState == 'complete') onScriptLoad();
      }
      scriptTag.onload = onScriptLoad;

      var s = $document[0].getElementsByTagName('body')[0];
      s.appendChild(scriptTag);

      return {
        d3: function() { return d.promise; }
      };
}]);

angular.module('DTBS.directives', [])
  .directive('d3Bars', ['d3Service', function (d3Service) {
    return {
      restrict: 'EA',
      scope: {},
      link: function(scope, element, attrs) {
        d3Service.d3().then(function(d3) {
          // d3 code goes here
          var svg = d3.select(element[0])
          .append("svg")
          .style('width', '100%');

          scope.render = function (data) {
            // remove all previous items before render
            svg.selectAll('*').remove();
            // If we don't pass any data, return out of the element
            if (!data) return;
            svg.selectAll('rect')
            .data(data).enter()
            .append('rect')
            .attr('height', 50)
            .attr('width', 50)
            .style('background-color', red)
          };

          // set up watch to see if button clicked; add rectangle with render func
          scope.$watch('data', function(newVals, oldVals) {
            console.log("hey")
            return scope.render(newVals);
          }, true);
        });
      }};
  }]);

在我的代码的主要部分,我有一个名为'DTBS.test'的模块。该模块有一个表控制器,它具有一个名为'save'的功能。我希望我的d3指令监视要调用的这个save函数,当它被调用时,应调用render函数向svg添加一个矩形。

angular.module('DTBS.test', [])
.controller('TableController', ['$scope', function ($scope) {
    var secondsToWaitBeforeSave = 3;
    $scope.table = {};
    //Table save function that clears form and pushes up to the parent
    $scope.save = function () {
      $scope.id++;
      $scope.table.id = $scope.id;
      $scope.table.attrs = [];
      $scope.addTable($scope.table);
      $scope.table = {};
    };

  }])

目前正在观察不存在的“数据”变化 - 我的问题是它应该注意什么以及如何将测试模块控制器中的事件链接到d3模块指令中的手表设置?

2 个答案:

答案 0 :(得分:2)

我会创建一个中间数据服务,这样任何事情都可以操纵D3数据。该数据服务可以广播事件,您的指令可以捕获以重新呈现您的数据。

.service('d3Data', ['$rootScope', function($rootScope) {
  var data = [];
  var emit = function(data) { $rootScope.$broadcast('d3:new-data', data); }
  var api = {
    get: function() {
      return data;
    },
    set: function(data) {
      data = data;
      emit(data);
      return data;
    },
    push: function(datum) {
      data.push(datum);
      emit(data);
      return data;
    }
  }

  return api;
}])

我已经创建了一些小助手功能,以备你需要时使用。你的指令不会改变很多。只需添加一种方法来捕捉事件而不是watch。您可以将其放在scope.render功能下方。

scope.$on('d3:new-data', function(e, data) {
   scope.render(data);
});

接下来,您将拥有想要与D3图表对话的控制器。

.controller('TableController', ['$scope', 'd3Data', function ($scope, d3Data) {
  $scope.table = {};
  //Table save function that clears form and pushes up to the parent
  $scope.save = function(data) {
    data = angular.copy(data);
    d3Data.push(data);
  };
}])

模板将通过ng-models为save函数提供数据。假设您在模板中有一些输入,包括table.widthtable.height等ng模型,然后在提交按钮中可以放置ng-click="save(table)"。然后我们复制该数据,使其不再双向绑定到表单。并使用我们的新d3Data服务推送数据,该服务将广播一条消息,该指令将捕获并更新数据。

我创建了一个简单的Plunk来演示这个。 http://plnkr.co/edit/VMRNvZ?p=preview

答案 1 :(得分:0)

我看到的一个大问题是data变量仅在render函数中可用。您在$watch render data之外的undefined内呼叫scope.data; scope.render = function (data) { scope.data = data; // some code here } scope.$watch('data', function(newVals, oldVals) { }

一个简单的解决方案如下:

public static void main(String[] args) {

        BufferedImage resim=null;
        File f=null;

        try {
            f=new File("C:\\Users\\burak\\Desktop\\javaresim\\1.jpg");
            resim=ImageIO.read(f);

        } catch (Exception e) {
            e.printStackTrace();
        }

          yük=resim.getHeight();
          gen=resim.getWidth();
          boyut=(gen*yük);


         for(int i=0;i<gen;i++){
              for(int j=0;j<yük;j++){

                  int p=resim.getRGB(i, j);

                  int a=(p&0xff000000)>>24;
                  int r=(p&0x00ff0000)>>16;
                  int g=(p&0x0000ff00)>>8;
                  int b=p&0x0000000ff;

                  System.out.print(r+" ");

                  p=(a<<24)|(r<<16)|(g<<8)|b;
                  resim.setRGB(i, j, p);
              }
         }

         try{
             f=new File("C:\\Users\\burak\\Desktop\\javaresim\\2.jpg");

             ImageIO.write(resim, "jpg", f);

            }catch(Exception e){
             e.printStackTrace();
              } 
           }      
}