如何在Angular中的自定义指令中设置d3图表?

Kod*_*_12 2 javascript d3.js angularjs

我一直在关注如何在角度应用程序中实现d3图表.基本上,我试图将以下d3图表实现到我的自定义角度指令('workHistory')中.出于这个问题的目的,我正在遵循一个简单的条形图示例,我将其设置为:

的index.html

<!doctype html>
    <html lang="en" ng-app="webApp">
    <head>
        <meta charset="utf-8">

        <title>My Portfolio</title>

        <!--Stylesheets -->
        <link rel="stylesheet" href="styles/main.css"/>
        <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.min.css"/>
        <!--Libraries -->
        <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
        <script src="bower_components/jquery/dist/jquery.min.js"></script>
        <script src="bower_components/angular-route/angular-route.min.js"></script>
        <script src="bower_components/angular-loader/angular-loader.min.js"></script>
        <script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
        <script src="bower_components/d3/d3.min.js"></script>
        <!--Module -->
        <script src="scripts/modules/module.js"></script>
        <script src="scripts/modules/d3.module.js"></script>
        <!--Controllers -->
        <script src="scripts/controllers/mainHeroController.js"></script>
        <script src="scripts/controllers/workHistoryController.js"></script>
        <!--Directives-->
        <script src="scripts/directives/mainHero.directive.js"></script>
        <script src="scripts/directives/mainNavbar.directive.js"></script>
        <script src="scripts/directives/workHistory.directive.js"></script>
    </head>

     <!--Main Landing Page-->    
    <body ng-app="webApp">
        <div id="container1"> 
            <work-history chart-data="myData"></work-history>
        </div>
        <div id="container2">
            Container 2
        </div>
    </body>
    </html>
Run Code Online (Sandbox Code Playgroud)

workHistory.directive.js

(function()
{
    'use strict';

    angular
        .module('webApp')
        .directive('workHistory', workHistory);

    function workHistory()
    {
        var directive = 
            {
                restrict: 'EA',
                controller: 'WorkHistoryController',
                //controllerAs: 'workhistory',
                scope: {data: '=chartData'},
                template: "<svg width='850' height='200'></svg>",
                link: workHistoryLink,
            };

        return directive;
    }

    function workHistoryLink(scope, element/*, attrs, ctrl, tfn*/)
    {

       var chart = d3.select(element[0]);
        chart.append("div").attr("class", "chart")
         .selectAll('div')
         .data(scope.data).enter().append("div")
         .transition().ease("elastic")
         .style("width", function(d) { return d + "%"; })
         .text(function(d) { return d + "%"; });
         } 
})();
Run Code Online (Sandbox Code Playgroud)

的main.css

.axis path,
.axis line{
  fill: none;
  stroke:black;
  shape-rendering:crispEdge;
}

.axis text{
  font-family: sans-serif;
  font-size: 10px;
}

h1{
  font-family: sans-serif;
  font-weight: bold;
  font-size: 16px;
}
.tick
{
  stroke-dasharray: 1, 2;
}
Run Code Online (Sandbox Code Playgroud)

问题: 使用此代码,不显示任何内容.我收到以下错误:

angular.js:13920TypeError:chart.append(...).attr(...).selectAll(...).data(...).enter不是函数

有人可以帮我理解如何正确设置吗?(如果有人可以解释我如何将可折叠树d3图表配置为自定义指令,则可以获得奖励.

谢谢.

Ste*_*ane 5

您的代码中有几个错误:

  1. 你的模板不好:你制作一个svg,但你在里面插入标准的html标签.它不可能奏效.在这种情况下,您应该创建一个带有div标签的模板作为根节点.
  2. 如果要像提供的那样提供初始模板,则应通过将指令的replace属性设置为true将其作为根节点.
  3. 然后,如果你想要d3可见的div添加,你应该通过设置背景或带有".style('background','blue')"的边框来使它们可见.
  4. 我不明白你可以在控制器'WorkHistoryController'中做什么.据我所知,在这样的指令中,你应该避免同时提供链接和控制器.
  5. 最后,如果你想让整个思想始终有效,你应该将D3代码放入$ watch中,这样你就可以确保在范围内设置数据后触发生成.
  6. 作为补充,现在你的图形总是在观察数组,如果数组比以前小,它应该处理不必要的元素的删除:".exit().remove();"

该指令应如下所示:

angular
    .module('app', [])
    .directive('workHistory', workHistory);

function workHistory()
{
    var directive = 
        {
          restrict: 'EA',
          scope: {data: '=chartData'},
          replace:true,
          template: "<div style='width:100%'></div>",
          link: workHistoryLink,
        };

    return directive;
}

function workHistoryLink(scope, element)
{
  scope.$watch('data', function(){
    var chart = d3.select(element[0]);
    chart.append("div").attr("class", "chart")
      .selectAll('div')
      .data(scope.data).enter().append("div")
      .style('background', 'blue')
      .transition().ease("elastic")
      .style("width", function(d) { return d + "%"; })
      .text(function(d) { return d + "%"; })
      .exit().remove();
  }, true);
} 
Run Code Online (Sandbox Code Playgroud)

这是一个jsbin来说明我的观点:http://jsbin.com/vegesigevi/edit?html,js,output

希望这可以帮助