【问题标题】:Using D3.js with Angular 2在 Angular 2 中使用 D3.js
【发布时间】:2016-01-27 21:34:18
【问题描述】:

我已成功将 Angular 2 (Alpha 44) 与 D3.js 集成:

<html>
<head>
<title>Angular 2 QuickStart</title>
<script src="../node_modules/systemjs/dist/system.src.js"></script>
<script src="../node_modules/angular2/bundles/angular2.dev.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>
<script>
  System.config({packages: {'app': {defaultExtension: 'js'}}});
  System.import('app/app');
</script>
</head>
<body>
<my-app>Loading...</my-app>
</body>
</html>

app.js:

/// <reference path="./../../typings/tsd.d.ts" />

import {Component, bootstrap, ElementRef} from 'angular2/angular2';

@Component({
  selector: 'my-app',
  template: '<h1>D3.js Integrated if background is yellow</h1>',
  providers: [ElementRef]
})
class AppComponent { 
  elementRef: ElementRef;

  constructor(elementRef: ElementRef) {
   this.elementRef = elementRef;
  }

afterViewInit(){
    console.log("afterViewInit() called");
    d3.select(this.elementRef.nativeElement).select("h1").style("background-color", "yellow");
  }
}
bootstrap(AppComponent);

一切正常。但 ElementRef 的 Angular 2 文档声明如下:

当需要直接访问 DOM 时,将此 API 用作最后的手段。改用 Angular 提供的模板和数据绑定。或者,您可以查看 {@link Renderer},它提供了即使不支持直接访问本机元素也可以安全使用的 API。依赖直接 DOM 访问会在您的应用程序和渲染层之间创建紧密耦合,这将导致无法将两者分开并将您的应用程序部署到 Web Worker 中。

现在的问题是如何将 D3.js 与 Renderer API 集成?

【问题讨论】:

  • 我也在尝试让 D3 与 angular 2 一起工作。在上面的示例中,我可以看到您在 index.html 中引用了 d3 脚本,但我看不出您是如何获取 app.js 中的 d3 变量?
  • @user2915962 - npm install d3 ,确保安装后运行并且 d3.d.ts 由 tsd 创建,然后 import * as d3 from 'd3/d3';
  • 这里有一个 cmets 提到的视频:stackoverflow.com/q/34704148/2050479 很有趣
  • @urosjarc - 那是 Angular 1,它有一种非常不同的方式来做这些事情。

标签: angular d3.js


【解决方案1】:

要使用 Renderer,您需要原始 HTML 元素(又名 nativeElement)。所以基本上你必须使用你的库,获取原始元素并将其传递给渲染器。

例如

// h3[0][0] contains the raw element
var h3 = d3.select(this.el.nativeElement).select('h3');
this.renderer.setElementStyle(h3[0][0], 'background-color', 'blue');

关于 ElementRef 的警告是关于直接使用它。这意味着不鼓励这样做

elementRef.nativeElement.style.backgroundColor = 'blue';

不过没关系

renderer.setElementStyle(elementRef.nativeElement, 'background-color', 'blue');

为了显示目的,您也可以将它与 jQuery 一起使用

// h2[0] contains the raw element
var h2 = jQuery(this.el.nativeElement).find('h2');
this.renderer.setElementStyle(h2[0], 'background-color', 'blue');

不过,我的建议是坚持使用 angular2 提供的功能,无需依赖其他库即可轻松完成此操作。

使用纯 angular2,您有两种简单的方法

  • 使用指令
// This directive would style all the H3 elements inside MyComp
@Directive({
    selector : 'h3',
    host : {
        '[style.background-color]' : "'blue'"
    }
})
class H3 {}

@Component({
    selector : 'my-comp',
    template : '<h3>some text</h3>',
    directives : [H3]
})
class MyComp {}
  • 将 ViewChild 与局部变量一起使用
@Component({
    selector : 'my-comp',
    template : '<h3 #myH3>some text</h3>',
})
class MyComp {
    @ViewChild('myH3') myH3;
    ngAfterViewInit() {
        this.renderer.setElementStyle(this.myH3.nativeElement, 'background-color', 'blue');
    }
}

这是plnkr,其中包含我在此答案中提到的所有案例。当然,您的要求可能会有所不同,但请尽量使用 angular2。

【讨论】:

  • 那么,对于使用 bootstrap 的折叠插件的示例,我是否正确地说 jQuery(this.el.nativeElement).collapse('show'); 将是一种完全可以接受的插件实例化方式?
  • 我猜指令方法不适用于动态附加的 h3 对吧?示例:plnkr.co/edit/U2lvYqtGvdf7kWoRg10N?p=preview
【解决方案2】:

我在使用 ElementRef 时遇到了问题,我不确定该 API 是否已更改。所以我最终使用 ViewContainRef 来获取 nativeElement。

import {Component, ViewContainerRef, OnInit} from '@angular/core';
declare var d3:any;
@Component({
    selector: 'line-chart',
    directives: [],
    template: `<div class="sh-chart">chart</div>`
})
export class LineChart implements OnInit{
    elem ;
    constructor(private viewContainerRef:ViewContainerRef) {}
    ngOnInit(){
        this.elem = this.viewContainerRef.element.nativeElement;

        d3.select(this.elem).select("div").style("background-color", "yellow");
    };
}

【讨论】:

    【解决方案3】:

    试试这个:

    npm install d3@3.5.36 --save设置你需要的版本

    npm install @types/d3@3.5.36 --save 如果你想要 d3 4+ 或更高版本

    然后在你的ts

    import * as d3 from 'd3';

    应该没问题

    【讨论】:

    • 使用最新的 d3 (v4) 并基于 Angular 2 快速入门示例,我还必须将 'd3':'npm:d3' 添加到 map 并将 'd3': {main:'build/d3.js', defaultExtension:'js'} 添加到 systemjs.config.js 文件中的包中。
    • 嗨@Entrodus,您介意根据快速入门给我确切的安装顺序吗?我试图遵循这一点,包括您提出的系统 mod,但我仍然卡住(没有 ./build/d2.js,也没有 ./build 文件夹)。
    • @StéphanedeLuca: 1.设置 Angular 快速入门 > 2.安装 d3 和 d3 版本 4.4.0 的类型 > 3.在 system.config.js 中添加 d3 的映射和包指令 > 4.add在使用 d3 > 5.Victory 的角度组件中导入 d3。
    【解决方案4】:
    npm install --save d3
    

    在 package.json 中检查 d3 版本并在 node_modules 中也检查它。

    然后,在component.ts中,如下导入

    import * as d3 from 'd3';
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-08
      • 2013-12-12
      • 1970-01-01
      • 2016-12-07
      • 1970-01-01
      • 1970-01-01
      • 2020-07-28
      • 2017-05-21
      相关资源
      最近更新 更多