web-dev-qa-db-ja.com

D3.jsのコンポーネントのスタイルがangular 2に表示されない

Angular 2とD3.jsを使用しています。赤い長方形を表示したいです。

スタイルをstyle.cssファイルに入れた場合にのみ機能します。チェック this plunkr

コンポーネントにスタイルを配置するとstyles: []、動作しません。チェック this plunkr

コンポーネントを使用するときに機能させる方法styles: []?ありがとう

UPDATE:@micronyksはソリューションを提供しますが、コンポーネントのスタイルをグローバルにします。基本的にstyle.cssファイル。 this plunkr では、あるコンポーネントのスタイルが別のコンポーネントのスタイルをオーバーライドすることを示しているため、緑と赤の長方形を表示できません。

UPDATE 2:@Günterの方法はこの問題を完全に解決します!! Günterのやり方を思い出してください。少なくともAngular beta 10が必要です。(他のプランカーは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());
  }
}
32
Hongbo Miao

更新

AngularとSASSは、::ng-deepまたはブラウザ標準に準拠するものがすべてのブラウザで使用可能になるまで、>>>/deep/または::slottedの代わりに)をサポートすることに少し同意しました。

ViewEncapsulation.Emulated(デフォルト)

それは設計によるものです。 Angularは、コンポーネントに固有のクラス名を追加し、追加されたスタイルを、それらが追加されたコンポーネントにのみ適用されるように書き換えます。

D3は、Angularsの知識がなくてもHTMLを動的に生成し、Angularはクラスを適用して、生成されたHTMLにスタイルを適用できません。

エントリポイントのHTMLファイルにスタイルを追加すると、Angularもスタイルを書き換えず、追加されたヘルパークラスは有効になりません。

ViewEncapsulation.None

encapsulation: ViewEncapsulation.Noneの場合Angularはこの書き換えを行わないため、結果はHTMLをindex.htmlに追加することに似ています。

「シャドウピアス」

または、最近導入されたシャドウピアスCSSコンビネーター>>>/deep/、および::shadowを使用できます(::shadowはaに置き換えられているため、非常に制限されています)。 https://stackoverflow.com/a/36225709/217408 および Plunker も参照してください

:Host /deep/ div {
  color: red;
}

[〜#〜] sass [〜#〜]

/deep/はSASSで正常に動作しますが、エイリアス>>>は動作しません。

シャドウピアスCSSコンビネーターはAngularによって書き換えられ、ブラウザーでサポートされる必要はありません。Chromeしばらくサポートされていますが、非推奨-ただし、前述のとおり、Angularはカプセル化エミュレーションを使用するように書き換えるので、問題ではありません。

ViewEncapsulation.Native

Angularは、そのようなコンポーネントを外部からスタイルする方法をサポートしていません。ブラウザがCSS変数などのサポートを提供する場合にのみ、これらを使用できます。

43

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: []
})
19
micronyks

カプセル化を表示

これは、ビューのカプセル化がAngular 2.であるためです。デフォルトでは、すべてのHTMLおよびCSSは、ローカルにのみ適用されるように変換されます。つまり、このスタイルをコンポーネントのCSS :

h2 { color: red; }

アプリケーション全体のすべてのh2要素ではなく、コンポーネント内のh2要素のみに影響します。このメカニズムの詳細については、 Angular 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を使用していない場合は、外部スタイルシートを追加する方法が必要です。おそらく最も簡単な方法は、<link …>内に別の<head>を追加することです。 index.htmlファイル。

ViewEncapsulation.None

最初のオプションは、チャート(およびチャートのみ)でコンポーネントを作成し、その中のカプセル化の表示をオフにすることです。また、単一の責任原則に従うため、これを行うことをお勧めします。設計上、チャートは別のコンポーネントにカプセル化する必要があります。ビューのカプセル化の有効化は、@Componentデコレータに別のプロパティを追加するのと同じくらい簡単です。

@Component({
    …
    encapsulation: ViewEncapsulation.None
})

/deep/ CSSセレクター

何らかの理由でそれをしたくない場合は、別の可能性があります。 CSS内で/deep/セレクターを使用して、スタイルをすべての子コンポーネントビューに強制することができます。事実上、これはカプセル化を破壊し、C3チャートに影響するはずです。そのため、たとえば、コンポーネントのCSSファイルでそれを行うことができます。

/deep/ .c3-chart-arc path {
    stroke: white;
}

いずれにせよ、これが起こる理由と動作を理解するために、前述の View Encapsulation in Angular 2 の前述のドキュメントを読むことをお勧めします。トラブルを引き起こさないコード:)この記事は、それがどのように機能するかを理解するのに役立つかもしれません: blog.thoughtram.ioでカプセル化を見る

7
2
Mihail

...その後、1つの赤と1つの緑の長方形を表示できません...問題が再発します

私はそれがいくつかのオーバーライドだと思う、私はこれのどれくらいが真実かわからないが、これはあなたの問題を解決すると思う.

たとえば、child1-cmpchild1-cmp .barを追加します。

@Component({
  encapsulation: ViewEncapsulation.None,
  selector: 'child1-cmp',
   styles: [`
    child1-cmp .bar {
      fill: red;
    }
  `],
  template: `
    <div>
      <svg class="chart1"></svg>
    </div>
  `,
  directives: []
})

注: micronyks で述べたように、encapsulation: ViewEncapsulation.Noneに加えて。

テスト

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

1
Angel Angel

見つけた * /deep/ .my-element-classは動作しますが、何らかの理由で、svg親要素がhtmlテンプレートに存在する場合のみ(d3によってsvg親要素がオンザフライで作成される場合ではありません)。

たとえば、次の状況が機能します。

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)
 ...
0
maia