D3.js 组件中的样式未以角度 2 显示
Posted
技术标签:
【中文标题】D3.js 组件中的样式未以角度 2 显示【英文标题】:Styles in component for D3.js do not show in angular 2 【发布时间】:2016-07-12 21:23:12 【问题描述】:我正在使用 Angular 2 和 D3.js。我想显示一个红色矩形。
仅当我将样式放入 style.css 文件时才有效。 检查this plunkr
当我将样式放入组件 styles: []
时,它不起作用。检查this plunkr
当我使用组件styles: []
时如何让它工作?谢谢
更新: @micronyks 提供了一个解决方案,但它使组件中的样式全局化,与 style.css 文件中的编写基本没有区别。在this plunkr中,显示一个组件的样式会覆盖另一个组件的样式,所以不能显示绿色和红色矩形。
更新 2: @Günter 的方式完美解决了这个问题!!提醒一下,对于 Günter 的方式:它至少需要 Angular beta 10。(我的其他 plunkrs 使用 Angular beta 8)使用 Angular beta 12 的绿色和一个红色矩形的工作演示是here。
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());
【问题讨论】:
似乎正在工作。你检查了吗? @micronyks 仅在style.css
文件中的 styes 时有效。
似乎在工作clipular.com/c/…
@Cyril 是的,当麦粒肿仅在 style.css
文件中时有效
【参考方案1】:
更新
Angular 和 SASS 不久前同意支持 ::ng-deep
(而不是 >>>
或 /deep/
),直到 ::slotted
或任何使其成为浏览器标准的东西在所有浏览器中都可用。
ViewEncapsulation.Emulated(默认)
这是设计使然。 Angular 添加了组件独有的类名,并将添加的样式重写为仅适用于添加它们的组件。
D3 在没有 Angular 知识的情况下动态生成 html,并且 Angular 无法应用这些类来使样式应用于生成的 HTML。
如果在入口点 HTML 文件中添加样式,Angular 也不会重写样式,添加的辅助类不会生效。
ViewEncapsulation.None
对于encapsulation: ViewEncapsulation.None
,Angular 不会进行这种重写,因此结果类似于将 HTML 添加到 index.html
。
“穿影”
或者,您可以使用最近引入的阴影穿透 CSS 组合 >>>
、/deep/
和 ::shadow
(::shadow
只是被
替换,因此非常有限)。另见https://***.com/a/36225709/217408 和Plunker
:host /deep/ div
color: red;
SASS
/deep/
可以在 SASS 中正常工作,但别名 >>>
不能。
阴影穿透 CSS 组合器由 Angular 重写,不需要浏览器支持。 Chrome 支持它们一段时间,但它们已被弃用 - 但正如所说,这并不重要,因为 Angular 会重写它们以使用其封装仿真。
ViewEncapsulation.Native
Angular 不支持以任何方式从外部设置此类组件的样式。只有当浏览器提供 CSS 变量等支持时,才能使用这些。
【讨论】:
谢谢你,君特!!它现在完美无缺!!那些穿透 CSS 组合器>>>
、/deep/
和 ::shadow
的东西太棒了!我觉得我需要学习的东西太多了。
只是提醒其他人:为此,它至少需要 Angular beta 10。(我的其他 plunkrs 使用 Angular beta 8)使用 Angular beta 12 的绿色和一个红色矩形的工作演示是here.
嗨,Günter,这些 CSS 组合器是否已弃用?如果是,那么还有其他方法吗? chromestatus.com/feature/6750456638341120
“这不起作用”不知道你认为我应该怎么做。你可能做错了什么,但我们怎么知道?
这有助于在折线图上显示数据点的“点”:将以下内容添加到我的 reportgraph.component.css
文件中:>>> #reportClubSignupRate .nv-point fill-opacity: 1 !important;
【参考方案2】:
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: []
)
【讨论】:
你能解释一下吗?这将更有帮助。谢谢 egghead.io/lessons/… 只需观看此视频一次,您就会了解 angular2 中可用的三种不同方式。 看完这个视频,基本上是让样式全局化了,然后就像在style.css
中使用一样,请看这个plunkr,然后我不能显示一个红色和一个绿色的矩形......问题又来了【参考方案3】:
查看封装
这是因为 Angular 2 中的视图封装。默认情况下,所有的 HTML 和 CSS 都经过转换,以便仅在本地应用。换句话说,如果您在组件的 CSS 中添加此样式:
h2 color: red;
它只会影响组件内的h2元素,而不是整个应用程序中的每个h2元素。您可以在Angular documentation on View Encapsulation 中阅读有关此机制的更多信息。
为什么会影响你?
Angular 会转换您的样式,但由于尚未绘制 C3 图形,它也无法转换 HTML/SVG。因此,组件样式不会匹配 C3 图中的元素。
我该怎么办?
外部样式表
视图封装机制不会转换外部样式表,因此它们会有效地影响您的 C3 图表(以及与此相关的任何其他元素)。
如果您使用 Angular CLI,添加外部样式表非常简单。
编辑您的angular-cli.json
文件并在apps
属性中找到styles
数组。在此处添加另一个样式表:
…
"apps": [
…
"styles": [
"styles.scss",
"c3.scss" // <---- add this or any other file
],
],
…
如果您不使用 Angular CLI,则必须有一些方法可以添加外部样式表。可能最简单的方法是在您的index.html
文件中的<head>
中添加另一个<link …>
。
ViewEncapsulation.None
您的第一个选项是:使用图表(并且只有图表)创建一个组件,然后关闭其中的 View Encapsulation。这样做也是一个好主意,因为它遵守单一职责原则。根据设计,您的图表应封装在单独的组件中。关闭视图封装就像在 @Component
装饰器中添加另一个属性一样简单:
@Component(
…
encapsulation: ViewEncapsulation.None
)
/deep/
CSS 选择器
如果出于某种原因,您不想这样做,还有另一种可能性。您可以尝试在 CSS 中使用 /deep/
选择器,这会将样式强制下放到所有子组件视图中。实际上,这会破坏封装并影响您的 C3 图表。因此,例如,您可以在组件的 CSS 文件中执行此操作:
/deep/ .c3-chart-arc path
stroke: white;
无论哪种方式,我都建议阅读View Encapsulation in Angular 2 上的上述文档,以了解为什么会发生这种情况以及它是如何工作的。此功能应该可以帮助您编写代码,而不是造成麻烦:) 本文可能会帮助您了解其工作原理:View Encapsulation on blog.thoughtram.io
【讨论】:
【参考方案4】:你可以使用
::ng-deep
.bar
fill: red;
Here you can read perfect article explaining the approach.
And... information from the Angular documentation
【讨论】:
请编辑此答案以响应特定问题的方式描述此代码的作用。【参考方案5】:...然后我不能显示一个红色和一个绿色的矩形...问题 回来了
我认为这是一些覆盖,我不知道这在多大程度上是正确的,但我认为这可以解决您的问题。
例如添加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所述。
测试
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: []
)
测试
Plunker
或者这个使用类.chart1
,.chart2
,例如如果你想要的话。
@Component(
selector: 'my-app',
directives: [Child1Cmp, Child2Cmp],
encapsulation: ViewEncapsulation.None,
styles: [`
.chart1 .bar
fill: red;
.chart2 .bar
fill: yellow;
`],
..//
测试
Plunker
【讨论】:
谢谢,@angel-angel,它们是非常好的替代方法,但我有几十个这样的小组件,每个组件也被重复使用数十甚至数百次。如果我不能将它们的样式限制在它们自己的组件中,那将很难维护。【参考方案6】:我发现* /deep/ .my-element-class
有效,但由于某种原因,只有当 svg 父元素存在于 html 模板中时(而不是当 svg 父元素由 d3 动态创建时)。
例如,以下情况会起作用:
我的组件.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)
...
【讨论】:
以上是关于D3.js 组件中的样式未以角度 2 显示的主要内容,如果未能解决你的问题,请参考以下文章