2016-08-25 12 views
1

d3の円グラフの例に従います。http://bl.ocks.org/mbostock/3887235です。テキストがd3円グラフのパスでカバーされています

私のコードの最小限のサンプル:

const container = $('#graph-pie'); 
const width = container.width() * 0.5; 
const height = 256; 
const radius = Math.min(width, height)/2; 

const color = d3.scaleOrdinal() 
    .range(['#869099', '#8c7853', '#007d4a']); 

const arc = d3.arc() 
    .outerRadius(radius - 10) 
    .innerRadius(0); 

const labelArc = d3.arc() 
    .outerRadius(radius - 40) 
    .innerRadius(radius - 40); 

const pie = d3.pie() 
    .sort(null) 
    .value((d) => { return d.value }); 

const svg = d3.select('#graph-pie').append('svg') 
    .attr('width', width) 
    .attr('height', height) 
.append('g') 
    .attr('transform', 'translate(' + width/2 + ',' + height/2 + ')'); 

const g = svg.selectAll('.arc') 
    .data(pie(totals)) 
    .enter() 
.append('g') 
    .attr('class', 'arc'); 

g.append('path') 
    .attr('d', arc) 
    .style('fill', (d) => { return color(d.data.name) }); 

g.append('text') 
    .attr('transform', (d) => { return 'translate(' + labelArc.centroid(d) + ')' }) 
    .attr('dy', '.35em') 
    .text((d) => { 
     return names[d.data.name]; 
    }); 

問題が時々ラベルのテキストは、円スライスの後ろに隠れて表示されていることです。私はこれがChromeで主に起こっていることに気付いていますが、他のブラウザでは起こっていないことはわかりません。いくつかの例:

Example 1

Example 2

Example 3

ことができます場合は、次のように出力されたSVGのコードは次のとおりです。

<div id="graph-pie" class="graph pie"> 
    <svg width="668" height="256"> 
    <g transform="translate(334,128)"> 
     <g class="arc"> 
     <path d="M7.225416114969383e-15,-118A118,118,0,0,1,98.56840842206363,-64.87117126383073L0,0Z" style="fill: rgb(134, 144, 153); z-index: 10;"> 
     <text transform="translate(41.753394753534344,-77.46388853237056)" dy=".35em">Sensitive</text> 
     </g> 
     <g class="arc"> 
     <path d="M98.56840842206363,-64.87117126383073A118,118,0,0,1,-27.95807360901471,114.64007205193529L0,0Z" style="fill: rgb(140, 120, 83);"> 
     <text transform="translate(71.92851960216296,50.69800851947991)" dy=".35em">Somewhat Sensitive</text> 
     </g> 
     <g class="arc"> 
     <path d="M-27.95807360901471,114.64007205193529A118,118,0,0,1,-2.167624834490815e-14,-118L0,0Z" style="fill: rgb(0, 125, 74);"> 
     <text transform="translate(-87.37132713286675,-10.500056906587716)" dy=".35em">Tolerant</text> 
     </g> 
    </g> 
    </svg> 
</div> 

私はいじり試してみましたz-index CSSスタイルですが、効果はなく、SVG要素のようには見えませんilar属性。テキスト要素をパスの上にレンダリングさせるにはどうすればよいですか?

答えて

0

あなたのコードでは、それぞれg(グループ)にパス要素とテキスト要素があるため、テキストはいくつかのパスでカバーされています。したがって、特定のグループの後にあるグループ内のパス(SVGの順番で、 "over it")は、その特定のテキストの後にレンダリングされ、それをカバーします。 SVGの "描画命令"は、この記事の最後に記載されています。

したがって、のすべてのパスをレンダリングした後に、テキストをレンダリングする必要があります。これを行うにはいくつかの方法がありますが、もっとも単純な方法(もっともエレガントではない方法です)は、テキストの別のグループを作成することです。

たとえば、これは現在あなたのコードです。

const width = 400 
 
const height = 400; 
 
const radius = Math.min(width, height)/2.5; 
 

 
const totals = [{"name":"Category A long label", "value":20}, 
 
\t \t   {"name":"Category B long label", "value":50}, 
 
\t \t   {"name":"Category C long label", "value":30}, 
 
\t \t \t \t \t \t \t {"name":"Category D long label", "value":20}, 
 
\t \t   {"name":"Category E long label", "value":50}, 
 
\t \t   {"name":"Category F long label", "value":30}]; 
 

 
const color = d3.scaleOrdinal() 
 
    .range(['#869099', '#8c7853', '#007d4a']); 
 

 
const arc = d3.arc() 
 
    .outerRadius(radius - 10) 
 
    .innerRadius(0); 
 

 
const labelArc = d3.arc() 
 
    .outerRadius(radius - 40) 
 
    .innerRadius(radius - 40); 
 

 
const pie = d3.pie() 
 
    .sort(null) 
 
    .value((d) => { return d.value }); 
 

 
const svg = d3.select('#graph-pie').append('svg') 
 
    .attr('width', width) 
 
    .attr('height', height) 
 
.append('g') 
 
    .attr('transform', 'translate(' + width/2 + ',' + height/2 + ')'); 
 

 
const g = svg.selectAll('.arc') 
 
    .data(pie(totals)) 
 
    .enter() 
 
.append('g') 
 
    .attr('class', 'arc'); 
 

 
g.append('path') 
 
    .attr('d', arc) 
 
    .style('fill', (d) => { return color(d.data.name) }); 
 

 
g.append('text') 
 
\t .attr("text-anchor", "middle") 
 
    .attr('transform', (d) => { return 'translate(' + labelArc.centroid(d) + ')' }) 
 
    .attr('dy', '.35em') 
 
    .text((d) => { 
 
     return d.data.name; 
 
    });
<script src="https://d3js.org/d3.v4.min.js"></script> 
 
<div id="graph-pie"></div>

そしてこれは同じコードですが、後にパスを描画するテキストの異なるグループとの:あなたは、いくつかのスライスで覆われているテキストの一部を見ることができます:

const width = 400 
 
const height = 400; 
 
const radius = Math.min(width, height)/2.5; 
 

 
const totals = [{"name":"Category A long label", "value":20}, 
 
\t \t   {"name":"Category B long label", "value":50}, 
 
\t \t   {"name":"Category C long label", "value":30}, 
 
\t \t \t \t \t \t \t {"name":"Category D long label", "value":20}, 
 
\t \t   {"name":"Category E long label", "value":50}, 
 
\t \t   {"name":"Category F long label", "value":30}]; 
 

 
const color = d3.scaleOrdinal() 
 
    .range(['#869099', '#8c7853', '#007d4a']); 
 

 
const arc = d3.arc() 
 
    .outerRadius(radius - 10) 
 
    .innerRadius(0); 
 

 
const labelArc = d3.arc() 
 
    .outerRadius(radius - 40) 
 
    .innerRadius(radius - 40); 
 

 
const pie = d3.pie() 
 
    .sort(null) 
 
    .value((d) => { return d.value }); 
 

 
const svg = d3.select('#graph-pie').append('svg') 
 
    .attr('width', width) 
 
    .attr('height', height) 
 
.append('g') 
 
    .attr('transform', 'translate(' + width/2 + ',' + height/2 + ')'); 
 

 
const g = svg.selectAll('.arc') 
 
    .data(pie(totals)) 
 
    .enter() 
 
.append('g') 
 
    .attr('class', 'arc'); 
 
\t \t 
 
const g2 = svg.selectAll('.arc2') 
 
    .data(pie(totals)) 
 
    .enter() 
 
.append('g') 
 
    .attr('class', 'arc'); 
 
\t \t 
 

 
g.append('path') 
 
    .attr('d', arc) 
 
    .style('fill', (d) => { return color(d.data.name) }); 
 

 
g2.append('text') 
 
\t .attr("text-anchor", "middle") 
 
    .attr('transform', (d) => { return 'translate(' + labelArc.centroid(d) + ')' }) 
 
    .attr('dy', '.35em') 
 
    .text((d) => { 
 
     return d.data.name; 
 
    });
<script src="https://d3js.org/d3.v4.min.js"></script> 
 
<div id="graph-pie"></div>

あなたは、現在、テキストがカバーされていないことがわかります。

これはうまくいきますが、私が言ったように、SVGを調べると、1つの要素(意味をなさない)のグループが表示されるため、最もエレガントなアプローチではありません。別の方法として、パスとテキストを個別に作成する方法があります。これにはコードを少し変更する必要があります。


SVG:描画順序

これはイライラすることができるものです:あなたはD3を使用して可視化を行います。あなたが上に置いておきたい四角形が別の四角形の後ろに隠れているか、またはあなたがいくつかの円の後ろにいることを計画していた線が実際にそれを超えています。あなたのCSSでz-indexを使って解決しようとしますが、SVG 1.1ではうまくいきません。

説明は簡単です:SVGでは、要素の順序は "絵画"の順序を定義し、絵の順序は誰が上に行くのかを定義します。

SVGドキュメントフラグメント内の要素は、暗黙の描画順序を持ち、SVGドキュメントフラグメントの最初の要素が最初に塗りつぶされます。後続の要素は、以前にペイントされた要素の上にペイントされます。

だから、私たちはこのSVGを持っていることとします

<svg width="400" height=200> 
    <circle cy="100" cx="80" r="60" fill="blue"></circle> 
    <circle cy="100" cx="160" r="60" fill="yellow"></circle> 
    <circle cy="100" cx="240" r="60" fill="red"></circle> 
    <circle cy="100" cx="320" r="60" fill="green" z-index="-1"></circle> 
</svg> 

彼は4つの円を持っています。青い円は最初の "塗装された"ものなので、他のすべてのものに悩まされます。それから私たちは黄色いもの、次に赤いもの、そして最後に緑のものを持っています。緑色のものが最後のもので、それが一番上に表示されます。

enter image description here

だから、それは要素の順序を変更することが可能であるD3でSVG要素の順序を変更する:

これは、それがどのように見えるのですか?緑色の円の前に赤い円を描くことはできますか?

はい。あなたが念頭に置いておく必要がある最初のアプローチは、コード内の行の順序です。まず背景の要素を描画し、後でコードでは前景の要素を描画します。

しかし、要素を塗りつぶした後でも要素の順序を動的に変更できます。これを行うために書くことができるいくつかのプレーンなJavaScript関数がありますが、D3はすでに2つの素晴らしい機能、selection.raise()とを持っています。 APIによる

selection.raise():再挿入各選択された要素、順番に、その親の最後の子として。 selection.lower():選択した各要素を親の最初の子として順番に再挿入します。

だから、私たちの前のSVGの要素の順序を操作する方法を示すために、ここでは非常に小さなコードです:それは

d3.selectAll("circle").on("mouseover", function(){ 
    d3.select(this).raise(); 
}); 

何をしますか?すべてのサークルが選択され、ユーザーが1つのサークル上にカーソルを置くと、そのサークルが選択されて前面に表示されます。非常に簡単です!

ライブコードとhere is the JSFiddleです。

関連する問題