Javascript AngularJS+;D3视图中使用的多个指令只有一个更新

Javascript AngularJS+;D3视图中使用的多个指令只有一个更新,javascript,css,angularjs,d3.js,Javascript,Css,Angularjs,D3.js,我有一个仪表图指令,需要在视图中放置多次,但控制器中的更新方法似乎只更新视图中的最后一个指令。起初,我认为可能我没有将作用域设置为一个孤立的作用域,但事实并非如此,这会引发一个错误,但视图确实加载了所有图表,但它只更新了一个图表 我对指令进行了一个简单的描述以提供帮助,并在下面包含了指令和控制器的基本存根。注意:刚刚开始使用D3并在指令中实现它,因此当您调整浏览器大小时,指令会成倍增加(试图使其响应),因此您可能在代码笔中调整浏览器窗口大小后点击了保存 .directive('d3Gauge

我有一个仪表图指令,需要在视图中放置多次,但控制器中的更新方法似乎只更新视图中的最后一个指令。起初,我认为可能我没有将作用域设置为一个孤立的作用域,但事实并非如此,这会引发一个错误,但视图确实加载了所有图表,但它只更新了一个图表

我对指令进行了一个简单的描述以提供帮助,并在下面包含了指令和控制器的基本存根。注意:刚刚开始使用D3并在指令中实现它,因此当您调整浏览器大小时,指令会成倍增加(试图使其响应),因此您可能在代码笔中调整浏览器窗口大小后点击了保存

  .directive('d3Gauge', [
    'D3GaugeConfig',
    function(D3GaugeConfig) {

      return {
        restrict: 'E',
        scope: {
          title: '@chartTitle',
          config: '=chartConfig',
          data: '=chartData'
        },
        link: link,
        template: '<div>{{d3GaugeCtrl.title}}</div>',
        controller: 'D3GaugeController',
        controllerAs: 'd3GaugeCtrl',
        bindToController: true
      };

      function link($scope, $element, $attrs) {
         ...

        // Browser onresize event
        $window.onresize = function() {
          $scope.$apply();
        };

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

        $scope.update = update;
      }

      function render(element, newValue) {
         ...
      }

      function update(newValue, newConfiguration) {

         ...
      }
    }
  ])

  .controller('D3GaugeController', [
    '$scope',
    function($scope) {

      var vm = this;

      function updateReadings() {

        // Just pump in random data here...
        if (angular.isDefined($scope.update)) {
          $scope.update(Math.random() * 100);
        }
      }

      // Every few seconds update reading values
      updateReadings();

      setInterval(function() {
        updateReadings();
      }, 5 * 1000);
    }
  ]);
.directive('d3Gauge'[
“D3GaugeConfig”,
功能(D3GaugeConfig){
返回{
限制:'E',
范围:{
标题:“@chartTitle”,
配置:'=chartConfig',
数据:'=图表数据'
},
链接:链接,
模板:“{d3GaugeCtrl.title}}”,
控制器:“D3GaugeController”,
controllerAs:'d3GaugeCtrl',
bindToController:true
};
函数链接($scope、$element、$attrs){
...
//浏览器调整大小事件
$window.onresize=function(){
$scope.$apply();
};
//注意调整大小事件
$scope.$watch(函数(){
返回angular.element($window)[0].innerWidth;
},函数(){
render($element,$scope.data);
});
$scope.update=更新;
}
函数呈现(元素,newValue){
...
}
函数更新(新值、新配置){
...
}
}
])
.控制器('D3GaugeController'[
“$scope”,
职能($范围){
var vm=这个;
函数updateReadings(){
//在这里输入随机数据。。。
if(角度.isDefined($scope.update)){
$scope.update(Math.random()*100);
}
}
//每隔几秒钟更新一次读取值
updateradings();
setInterval(函数(){
updateradings();
}, 5 * 1000);
}
]);

最后一个仪表发生变化的原因是:

您正在存储存储最后一条路径的变量指针

pointer = pg.append('path')
  .attr('d', pointerLine)
  .attr('transform', 'rotate(' + config.minAngle + ')');
那么现在当你这么做的时候

 pointer
      .duration(config.transitionMs)
      .ease('elastic')
      .attr('transform', 'rotate(' + newAngle + ')');
只有最后一个指针将使用新的转换进行更新

因此,如果要为相同的随机值更新所有仪表路径,请执行以下操作:

//select all the path in all svg with group class pointer  
d3.selectAll("svg .pointer path").transition()
          .duration(config.transitionMs)
          .ease('elastic')
          .attr('transform', 'rotate(' + newAngle + ')');//update the new angle
工作代码


希望这有帮助

嗨,如果我想让每一个都独立更新怎么办?这是不可能的。。。哦,我想我明白你的意思了(没有双关语),因为我把指令值存储在link函数之外,它们都共享这些值。在应用程序中,每个图表将相互独立,并根据不同的数据集进行更新。您通常如何设置一个D3指令,该指令是可重用的,而不必传递大量的函数参数。是否可以将指令实例包装到服务或其他东西中?如果我希望每个实例都独立更新,那么您的查询是不可能的:是的,您可以通过对变量实现$watch来实现这一点。因此,当变量更改时,手表将触发您的函数,您可以在其中更新路径。我已将“间隔”和“更新”函数移动到渲染中,因此现在它可以正常工作。在调整大小时,请检查代码中的另一个错误调用渲染方法…但在渲染方法中,您添加了svg和组件…等等你会发现你的仪表号在增加。为了修复上面提到的这个调整大小的错误,我制作了doResize函数,它将改变svg的宽度和高度,而不是调用render函数。