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

标签 javascript angularjs d3.js

我一直在关注一些关于如何在 Angular 应用程序中实现 d3 图表的演练。基本上,我试图实现以下 d3 chart进入我的自定义 Angular Directive(指令)('workHistory')。出于这个问题的目的,我正在关注一个简​​单的条形图 example我在哪里设置它:

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>

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 + "%"; });
         } 
})();

ma​​in.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;
}

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

angular.js:13920TypeError: chart.append(...).attr(...).selectAll(...).data(...).enter is not a function

有人可以帮助我了解如何正确设置吗? (奖金,如果有人可以解释我如何将可折叠树 d3 图表配置到自定义指令中。

谢谢。

最佳答案

您的代码中有几个错误:

  1. 你的模板不好:你制作了一个 svg,但是你在里面插入了标准的 html 标签。它不可能工作。在这种情况下,您应该制作一个带有 div 标签的模板作为根节点。
  2. 如果您想像您一样提供初始模板,则应通过将指令的 replace 属性设置为 true 使其成为根节点。
  3. 然后,如果您希望通过 d3 添加的 div 可见,您应该通过设置背景或带有“.style('background', 'blue')”的边框来使它们可见
  4. 我不明白您可以在 Controller “WorkHistoryController”中做什么。根据我的说法,在这样的指令中,您应该避免同时提供链接和 Controller 。
  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);
} 

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

希望对你有帮助

关于javascript - 如何在 Angular 中的自定义指令内设置 d3 图表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39559920/

相关文章:

javascript - jQuery 动画不适用于 SAPUI5

android - Cordova - 如何全屏和循环播放 mp4 视频?

javascript - 将元素内的 Html DOM 作为字符串传递给 AngularJS Controller

javascript - 如何创建带有背景图像的条形图

javascript - 在 Meteor.js 热代码重新加载上取消设置 session 变量

javascript - 在单独的进程中创建 iframe,这样它就不会阻塞父窗口的主线程

javascript - 动态添加和删除事件监听器

javascript - 如何使用 data-ng-repeat 获取从 A 到 Z 的索引值?

javascript - 图例点击和数据更新后c3js隐藏数据

javascript - d3.js - 使用 .selectAll() 根据属性值选择 Node 元素