【问题标题】:AngularJS + D3 Multiple Directives Used In View Only One UpdatesAngularJS + D3 使用的多个指令仅查看一个更新
【发布时间】:2015-12-01 08:30:41
【问题描述】:

我有一个仪表图指令需要多次放置在视图中,但控制器中的更新方法似乎只更新视图中的最后一个指令。最初我想也许我之前没有将范围设置为隔离范围,但事实并非如此,这只会引发错误,但视图确实加载了所有图表,但它只更新一个。

我制作了指令的codepen 来提供帮助,我在下面包含了指令和控制器的基本存根。注意:刚刚开始使用 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);
    }
  ]);

【问题讨论】:

    标签: javascript css angularjs d3.js


    【解决方案1】:

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

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

    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
    

    工作代码here

    希望这会有所帮助!

    【讨论】:

    • 嗨,如果我希望每个人都独立更新,那是不可能的......哦,我想我明白你在指出什么(不是双关语),因为我正在存储指令值在链接功能之外,它们都共享这些值。在应用程序中,每个图表将相互独立,并根据不同的数据集进行更新。您通常如何设置可重复使用而无需传递大量函数参数的 D3 指令。是否可以将指令实例包装到服务或其他东西中?
    • 您的查询如果我希望每个都独立更新是不可能的:是的,您可以通过在变量上实现 $watch 来做到这一点。因此,当变量更改时,手表将触发您可以更新路径的函数。
    • 我已经在渲染中移动了间隔和更新函数,所以现在它可以正常工作了检查codepen.io/anon/pen/VvoNQv?editors=001
    • 调整大小时调用渲染方法时代码中的另一个错误......但在渲染方法中,您正在附加 svg 和组件......所以在调整大小时,您会发现您的仪表编号增加。
    • 为了修复上面提到的这个调整大小错误,我制作了 doResize 函数,它将改变 svg 的宽度和高度......而不是调用渲染函数。 codepen.io/anon/pen/VvoNQv?editors=001
    猜你喜欢
    • 2014-02-14
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-28
    • 2014-10-19
    相关资源
    最近更新 更多