D3.js组件中的样式不以angular度2显示
我正在使用Angular 2和D3.js. 我想显示一个红色的矩形。
它只适用于style.css文件中的样式。 检查这个plunkr
当我把我的样式在组件styles: [] ,它不起作用。 检查这个plunkr 
 当我使用组件styles: []时如何让它工作styles: [] ? 谢谢 
更新: @micronyks提供了一个解决scheme,但它使全局组件中的样式,在style.css文件中写入基本没有区别。 在这个plunkr中 ,它显示一个组件中的样式会覆盖另一个组件的样式,所以不能显示绿色和红色的矩形。
更新2: @Günter的方式完全解决这个问题! 只是一个提醒,对Günter的方式:它至less需要Angular beta 10。(我的其他plunkrs使用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()); } } 
	
ViewEncapsulation.Emulated(默认)
这是devise。 Angular添加了组件特有的类名,并重写了添加的样式,仅适用于添加它们的组件。
D3没有Angulars的知识dynamic生成的HTML和Angular不能应用的类,使样式适用于生成的HTML。
如果您在入口点HTML文件中添加样式,Angular也不会重写样式,并且添加的助手类不会生效。
ViewEncapsulation.None
 使用encapsulation: ViewEncapsulation.None Angular不会执行此重写,因此结果类似于将HTML添加到index.html 。 
“影子刺穿”
 或者,您可以使用最近推出的阴影刺穿CSS组合器>>> , /deep/和::shadow ( ::shadow刚刚被replace为  因此非常有限)。 另见https://stackoverflow.com/a/36225709/217408和Plunker 
:host / deep / div {color:red; }
上海社会科学院
  /deep/与SASS正常工作,但别名>>>不。 
阴影parsingCSS组合器是由Angular重写的,并不需要浏览器支持。 Chrome支持他们一段时间,但是他们已经被弃用了,但是正如所说的那样,这并不重要,因为Angular重写了他们的封装模拟。
ViewEncapsulation.Native
Angular不支持从外部对这些组件进行样式化。 只有浏览器提供像CSSvariables这样的支持,才可以使用这些variables。
  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: [] }) 
视图封装
这是因为Angular 2中的视图封装。默认情况下,所有的HTML和CSS都被转换,所以只能在本地应用。 换句话说,如果你在组件的CSS中添加这个样式:
 h2 { color: red; } 
它只会影响组件中的h2元素 ,而不会影响整个应用程序中的每个h2元素。 您可以在View封装的Angular文档中阅读更多关于这种机制的内容 。
为什么会影响你?
Angular会转换你的样式,但是由于C3graphics还没有绘制,所以它也不能转换HTML / SVG。 因此,组件样式将不匹配C3图中的元素。
我该怎么办?
外部样式表
外部样式表不会被视图封装机制转换,所以它们会影响你的C3图表(以及任何其他元素)。
 如果您使用的是Angular CLI,添加外部样式表非常简单。 编辑您的angular-cli.json文件,并在apps属性中findstyles数组。 在这里添加另一个样式表: 
 { … "apps": [ { … "styles": [ "styles.scss", "c3.scss" // <---- add this or any other file ], } ], … } 
 如果你不使用Angular CLI,必须有一些方法来添加外部样式表。 也许最简单的是在你的index.html文件里添加<head>里的另一个<link …> 。 
 ViewEncapsulation.None 
 您的第一个select是:使用图表(仅图表)创build一个组件,并closures其中的视图封装。 遵守单一责任原则也是一个好主意。 您的图表在devise上应该封装在一个单独的组件中。 视图封装的转向与将@Component装饰器添加其他属性一样简单: 
 @Component({ … encapsulation: ViewEncapsulation.None }) 
  /deep/ CSSselect器 
 如果出于某种原因,你不想这样做,还有另一种可能性。 你可以尝试在你的CSS中使用/deep/ selector,这样可以将样式强制到所有的子组件视图中。 有效地,这打破封装,应该影响你的C3图表。 所以,例如,你可以在你的组件的CSS文件中做到这一点: 
 /deep/ .c3-chart-arc path { stroke: white; } 
无论哪种方式,我build议阅读前面提到的有关Angular 2中的视图封装的文档,以了解为什么发生这种情况以及它是如何工作的。 这个function应该可以帮助你编写代码,不会造成麻烦:)本文可能会帮助你理解它是如何工作的: 在blog.thoughtram.io上查看封装
…然后我不能显示一个红色和一个绿色的矩形…问题回来了
我认为这是一些覆盖,我不知道这是多less,但我认为这解决了你的问题。
 在child1-cmp , child1-cmp .bar中添加例如: 
 @Component({ encapsulation: ViewEncapsulation.None, selector: 'child1-cmp', styles: [` child1-cmp .bar { fill: red; } `], template: ` <div> <svg class="chart1"></svg> </div> `, directives: [] }) 
 注意:除了encapsulation: ViewEncapsulation.None ,正如由micronyks提到的。 
testing
Plunker
或这个:
 @Component({ selector: 'my-app', directives: [Child1Cmp, Child2Cmp], encapsulation: ViewEncapsulation.None, styles: [` child1-cmp .bar { fill: red; } child2-cmp .bar { fill: yellow; } `], ..// 
 @Component({ //encapsulation: ViewEncapsulation.None, selector: 'child1-cmp', template: ` <div> <svg class="chart1"></svg> </div> `, directives: [] }) 
 @Component({ //encapsulation: ViewEncapsulation.None, selector: 'child2-cmp', template: ` <div> <svg class="chart2"></svg> </div> `, directives: [] }) 
testing
Plunker
 或者这个使用类.chart1 , .chart2 ,例如,如果你想。 
 @Component({ selector: 'my-app', directives: [Child1Cmp, Child2Cmp], encapsulation: ViewEncapsulation.None, styles: [` .chart1 .bar { fill: red; } .chart2 .bar { fill: yellow; } `], ..// 
testing
Plunker
 我发现* /deep/ .my-element-class可以工作,但是出于某种原因,只有当svg父元素出现在html模板中时(而不是当svg父元素由d3dynamic创build时)。 
例如,以下情况将起作用:
mycomponent.component.html
 <svg id="mygraph"></svg> <!-- IMPORTANT!! --> 
mycomponent.component.css
 * /deep/ .my-element-class { /* ... desired styles */ } 
mycomponent.component.ts
 d3.select("svg#mygraph").append("circle").classed("my-element-class", true) ...