D3.js组件中的样式不显示在角度2中

Hon*_*iao 34 d3.js typescript angular

我正在使用Angular 2和D3.js. 我想要显示一个红色矩形.

它只适用于我在style.css文件中放置样式.检查这个plunkr

当我将我的样式放在组件中时styles: [],它不起作用.检查这个plunkr

使用组件时如何让它工作styles: []?谢谢

更新: @micronyks提供了一个解决方案,但它使组件中的样式全局化,与style.css文件中的写入基本没有区别.在这个plunkr中,它显示一个组件中的样式将覆盖另一个组件的样式,因此无法显示绿色和红色矩形.

更新2: @Günter的方式完美解决了这个问题!只是提醒一下,对于Günter的方式:它至少需要Angular beta 10.(我的其他插件使用Angular beta 8)使用Angular beta 12的绿色和一个红色矩形的工作演示就在这里.

import {Component} from 'angular2/core'
@Component({
  selector: 'my-app',
  providers: [],
   styles: [`
    /*this does not work*/
    .bar {
      fill: red;
    }
  `],
  template: `
    <div>
      <svg class="chart"></svg>
    </div>
  `,
  directives: []
})
export class App {
  constructor() {}

  ngOnInit() {
    this.draw();
  }

  draw() {
    let data = [{name: 'A', value: 1}];
    let width = 400, height = 200;

    let x = d3.scale.ordinal().rangeRoundBands([0, width]);
    let y = d3.scale.linear().range([height, 0]);

    let chart = d3.select(".chart")
      .attr("width", width)
      .attr("height", height)
      .append("g");

    x.domain(data.map(function(d) { return d.name; }));
    y.domain([0, d3.max(data, function(d) { return d.value; })]);

    chart.selectAll(".bar")
      .data(data)
      .enter().append("rect")
      .attr("class", "bar")
      .attr("x", function(d) { return x(d.name); })
      .attr("y", function(d) { return y(d.value); })
      .attr("height", function(d) { return height - y(d.value); })
      .attr("width", x.rangeBand());
  }
}
Run Code Online (Sandbox Code Playgroud)

Gün*_*uer 46

ViewEncapsulation.Emulated(默认)

这是设计的.Angular添加了组件独有的类名,并重写了添加的样式,仅适用于添加它们的组件.

D3在没有Angulars知识的情况下动态生成HTML,而Angular不能应用类来使样式适用于生成的HTML.

如果在入口点HTML文件中添加样式,Angular也不会重写样式,并且添加的帮助程序类不会生效.

ViewEncapsulation.None

使用::ng-deepAngular不会执行此重写,因此结果类似于将HTML添加到>>>.

"影子刺穿"

或者,您可以使用最近推出的阴影穿孔CSS组合器/deep/,::slotted并且encapsulation: ViewEncapsulation.None(index.html仅由a代替>>>SASS工作正常,但别名/deep/没有.

阴影匹配的CSS组合器由Angular重写,它们不需要浏览器支持.Chrome支持它们一段时间但它们已被弃用 - 但正如所说,这无关紧要,因为Angular会重写它们以使用其封装模拟.

ViewEncapsulation.Native

Angular不支持从外部设置此类组件的任何方式.只有当浏览器提供CSS变量等支持时,才能使用这些变量.


mic*_*yks 20

ViewEncapsulation 将解决您的问题.

import {Component,ViewEncapsulation} from 'angular2/core'

@Component({
  selector: 'my-app',
  encapsulation: ViewEncapsulation.None,
  providers: [],
   styles: [`
     .bar {
       fill: red;
    }
  `],
  template: `
    <div>
      <svg class="chart"></svg>
    </div>
  `,
  directives: []
})
Run Code Online (Sandbox Code Playgroud)

  • https://egghead.io/lessons/angular-2-controlling-how-styles-are-shared-with-view-encapsulation只需看一次该视频,您就会意识到angular2提供了三种不同的方式。 (2认同)

Mic*_*zyn 7

查看封装

这是因为Angular 2中的视图封装.默认情况下,所有HTML和CSS都被转换,因此它只在本地应用.换句话说,如果您在组件的CSS中添加此样式:

h2 { color: red; }
Run Code Online (Sandbox Code Playgroud)

它只会影响组件内的h2元素,而不会影响整个应用程序中的每个h2元素.您可以在View Encapsulation的Angular文档中阅读有关此机制的更多信息.

为什么它对你有影响?

Angular会转换您的样式,但由于尚未绘制C3图形,因此它也无法转换HTML/SVG.因此,组件样式将不匹配C3图形内的元素.

我该怎么办?

外部样式表

外部样式表不会被View Encapsulation机制转换,因此它们会有效地影响您的C3图表(以及任何其他元素).

如果您使用的是Angular CLI,添加外部样式表非常简单.编辑您的angular-cli.json文件和apps属性内部查找styles数组.在这里添加另一个样式表:

{
    …
    "apps": [
        {
            …
            "styles": [
                "styles.scss",
                "c3.scss" // <---- add this or any other file
            ],
        }
    ],
    …
}
Run Code Online (Sandbox Code Playgroud)

如果您不使用Angular CLI,必须有一些方法来添加外部样式表.可能最简单的是在文件中添加另一个<link …>内部.<head>index.html

ViewEncapsulation.None

您的第一个选项是:使用图表(仅限图表)创建组件并关闭其中的View Encapsulation.因为遵守单一责任原则,这也是一个好主意.根据设计,您的图表应封装在单独的组件中.转换视图封装就像向@Component装饰器添加另一个属性一样简单:

@Component({
    …
    encapsulation: ViewEncapsulation.None
})
Run Code Online (Sandbox Code Playgroud)

/deep/ CSS选择器

如果出于某种原因,你不想这样做,还有另一种可能性.您可以尝试/deep/在CSS中使用选择器,它将样式强制转换为所有子组件视图.实际上,这会打破封装并影响您的C3图表.因此,例如,您可以在组件的CSS文件中执行此操作:

/deep/ .c3-chart-arc path {
    stroke: white;
}
Run Code Online (Sandbox Code Playgroud)

无论哪种方式,我建议阅读上面关于Angular 2中的View Encapsulation的文档,以了解为什么会发生这种情况以及它是如何工作的.这个功能可以帮助你编写代码,而不会引起麻烦:)本文可能会帮助你理解它的工作原理:在blog.thoughtram.io上查看封装


Mih*_*ail 7

您可以使用

::ng-deep
.bar {
    fill: red;
}
Run Code Online (Sandbox Code Playgroud)

在这里您可以阅读解释该方法的完美文章。

还有...来自 Angular 文档的信息

  • 请编辑此答案,以响应特定问题的方式描述此代码的作用。 (2认同)