javascript - 使用 d3 动画 ng-repeat 指令模板的问题

标签 javascript angularjs d3.js

我正在尝试使用 Angular 和 D3 制作类别列表。我为此列表创建了一个指令,我的模板中的一些子节点使用 ng-repeat,因为我希望使用 angular 构建我的 html 而不是 d3。

我的问题是,当尝试使用 d3 引用 ng-repeated 元素时,它们尚未创建。如果我使用链接功能,则列表中没有任何项目。如果我使用编译功能,我可以看到 1 个列表项,但应该至少有 2 个。

Seen Here

取自 fiddle :

angular.module('myApp').directive('targetingCategories', function(){
  return {
    restrict: 'E',
    scope: {
      data: '='
    },
    template: '<div>'+
        '<ul class="catList">'+
          '<li ng-repeat="cat in data.categories">'+
            '{{cat.name}}'+
            '<ul class="subCatList">'+
              '<li ng-repeat="subcat in cat.categories">{{subcat.name}}</li>'+
            '</ul>'+
          '</li>'+
        '</ul>'+
      '</div>',
    replace: true,
    compile: function($tEl, $attrs){

      // attach d3 on the TEMPLATE element, and look for list items
      var vis = d3.select($tEl[0]);
      var catList = vis.select('.catList');
      var catListFirstItem = vis.select('.catlist>li');
      var catListItems = vis.selectAll('.catList>li');

      console.log(catList); // 1 item returned (the ul)
      console.log(catListFirstItem); // 1 item returned (the first li)
      console.log(catListItems); // 1 items returned ??

      return function($scope, $el, $attrs){
        // attach d3 to INSTANCE element and look for list items
        var vis = d3.select($el[0]);
        var catList = vis.select('.catList');
        var catListFirstItem = vis.select('.catlist>li');
        var catListItems = vis.selectAll('.catList>li');

        console.log(catList); // 1 item returned (the ul)
        console.log(catListFirstItem); // 1 item returned (the first li)
        console.log(catListItems); // 0 items returned ??
      };

    }
  };
});

我的想法是让 angular 构建我的标记,然后 d3 对其进行动画处理。与使用 CSS 动画相比,我喜欢 d3 给我的控制。

当我使用 d3 创建我的列表项时,这是 working just fine .我很想再次这样做,但我认为将 LI 放在模板中是一种更好的架构。

我在想我需要调用一个编译,或者等待一个或什么的。我的 Angular 知识几乎达到了极限,因此非常感谢这里的任何教育。

最佳答案

我正在添加我自己的潜在答案,但不做标记以防其他人有更好的答案。

目前,完成此任务的一种方法似乎是用其他嵌套指令替换主模板中的 LI,特别是“mainCategory”和“subCat”。然后我可以将 d3 附加到适当的实例元素以进行动画处理。通过包含一个索引属性,我可以控制延迟以使动画交错。感觉有点复杂和“ Backbone 式”(为了对象而对象),但它解决了我的问题。它还允许我附加一些 ng-clicks,这对于 d3 创建我的 LIs 来说是非常麻烦/不可能的。

是的,我知道我的属性称为“数据”并且可能有问题,但我现在并不担心。不过,对我使用服务/ Controller /指令的任何更正表示赞赏:)

updated JSFiddle

angular.module('myApp').directive('targetingCategories', function(){
  return {
    restrict: 'E',
    scope: {
      data: '='
    },
    template: '<div>'+
        '<ul class="catList">'+
          '<main-category ng-repeat="cat in data.categories" index="$index">'+
            '{{cat.name}}'+
            '<ul class="subCatList">'+
              '<sub-cat ng-repeat="subcat in cat.categories" index="$index" data="subcat">{{subcat.name}}</sub-cat>'+
            '</ul>'+
          '</main-category>'+
        '</ul>'+
      '</div>',
    replace: true
  };
});

angular.module('myApp').directive('mainCategory', function(targetingService){
  return {
    restrict: "E",
    scope: {
      index: "=",
      data: "="
    },
    template: '<li ng-transclude ng-click="selectCategory($event, data);"></li>',
    replace: true,
    transclude: true,
    link: function($scope, $el, $attrs){
      d3.selectAll($el).transition()
        .duration(500)
        .delay(function(){ return $scope.index*200; })
        .ease('elastic')
        .style('width', '100%')
        .style('padding', '10px');

      $scope.selectCategory = function($event, cat){
        $event.stopPropagation();
        targetingService.selectCategory(cat);
      };
    }
  };
});

angular.module('myApp').directive('subCat', function(targetingService){
  return {
    restrict: "E",
    scope: {
      index: '=',
      data: '='
    },
    template: '<li ng-transclude ng-click="selectSubCategory($event, data)"></li>',
    replace: true,
    transclude: true,
    link: function($scope, $el, $attrs){
      d3.selectAll($el).transition()
        .duration(100)
        .delay(function(d,i){ return 500+($scope.index*200); })
        .ease('linear')
        .style('height', '30px')
        .style('padding', '8px');

      $scope.selectSubCategory = function($event, subCat){
        $event.stopPropagation();
        targetingService.selectSubCategory(subCat);
      };
    }
  };
});

关于javascript - 使用 d3 动画 ng-repeat 指令模板的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21212024/

相关文章:

javascript - 正则表达式捕获除连续换行符之外的所有内容

javascript - 如何在 AngularJS 中使用 ng-repeat 数据进行计算

d3.js - d3 缩放到鼠标位置,而不是质心

javascript - D3JS中的自定义轴函数

javascript - 如何使用鼠标单击并拖动来放大D3

javascript - jquery 倒计时今天日期

javascript - 如何使用angularJS缩放图像

javascript - 0x800a1391 - JavaScript 运行时错误 : 'Stage' is undefined

javascript - 使用 Angular 根据表单输入从 MongoDB 中提取数据

javascript - AngularJS返回被拒绝的 promise