2013-11-21 13 views
8

個々の半径/直径に基づいてD3.jsが各ノードのフォントサイズを自動的に調整する方法を教えてください。私はD3.js個々の半径/直径のノードに基づく自動フォントサイズ設定

node.append("text") 
     .attr("dy", ".3em") 
     .style("text-anchor", "middle") 
     .text(function(d) { return d.className.substring(0, d.r/3); }) 
     .style("font-size", "10px") // initial guess 
//This is what gives it increased size... 
     .style("font-size", function(d) { return (2 * d.r - 10)/this.getComputedTextLength() * 10 + "px"; }) 

insize自動増加を可能にするスタイルを使用

。 * 10 + "px"; })

このエフェクトは、より小さいノードからテキストを削除します。私はまた、私は元の12 pxを覆う私の画面全体をカバーするドットを増やすことができるズーム機能を持っています。

.call(d3.behavior.zoom().scaleExtent([1, 200]).on("zoom", zoom)) 

ノードフォントを個別に自動的にフォーマットする方法はありますか。適切なサイズで書き込むため、呼び出されるノードのフォントをズームインすると、ノードのサイズに比例して表示されます。

enter image description here

右円を一覧表示します:NAME(SIZE)
私はから学ぶための作業例が大好きです。画像サイズでは、円の上に書かれているものを見るために拡大するまで、Pの隣にある駆動円の北の小さな緑の点に黒い読めない単語があります。目標は、ズームイン時に比例した読みやすいフォントを使用することです。

答えて

13

これは、コンテナのサイズに基づいてテキストサイズを動的に設定することによって行うことができます。このためには、テキストを追加し、境界ボックスを取得し、コンテナ要素の境界ボックスを取得し、現在のフォントサイズとその境界ボックスに基づいて正しいフォントサイズを取得する必要があります。

コードは次のようになります。

// ... 
    .append("text") 
    .text("text") 
    .style("font-size", "1px") 
    .each(getSize) 
    .style("font-size", function(d) { return d.scale + "px"; }); 

function getSize(d) { 
    var bbox = this.getBBox(), 
     cbbox = this.parentNode.getBBox(), 
     scale = Math.min(cbbox.width/bbox.width, cbbox.height/bbox.height); 
    d.scale = scale; 
} 
+0

作品は、優れた...単語の前後にスペースを取得したり、いくつかの手順小さいワードサイズを縮小するための簡単な修正はありますか? – Understood

+0

これは、 'cscale'がどのように決定されるかにあります。そこに因子を追加するか、スペースに対して' bbox.width'に一定のオフセットを追加することができます。 –

+0

このgetBBox()FFで問題を作成することがあります! –

1

ありがとうございましたOP &ありがとうございました(どちらもupvoted);私のテキストは、直径に沿って右に走っているのではなく、円の中でずらされていたので、少し違ってやってしまいました。テキストノードには、円内で上下にシフトする値がdyであり、これを使用して円上で測定したいコードを把握し、テキストを希望の高さのオフセットに自動調整します。また、ソースデータを変更するのではなく、テキスト要素のデータ属性に計算されたサイズを格納するほうがよいという私のニーズに応えました。将来にわたってこの問題を抱えている人にとっては役に立つかもしれないと思った。

jsfiddle

function appendScaledText(parentGroup, textVal, dyShift) { 
    parentGroup 
    .append("text") 
    .attr("dy", dyShift) 
    .attr("text-anchor", "middle") 
    .attr("dominant-baseline", "central") 
    .attr("font-family", "sans-serif") 
    .attr("fill", "white") 
    .text(textVal) 
    .style("font-size", "1px") 
    .each(getSize) 
    .style("font-size", function() { 
     return d3.select(this).attr("data-scale") + "px"; 
    }); 
} 

function getSize() { 
    var d3text = d3.select(this); 
    var circ = d3.select(this.previousElementSibling); // in other cases could be parentElement or nextElementSibling 
    var radius = Number(circ.attr("r")); 
    var offset = Number(d3text.attr("dy")); 
    var textWidth = this.getComputedTextLength(); // TODO: this could be bounding box instead 
    var availWidth = chordWidth(Math.abs(offset), radius); // TODO: could adjust based on ratio of dy to radius 
    availWidth = availWidth * 0.85; // fixed 15% 'padding' for now, could be more dynamic/precise based on above TODOs 
    d3text.attr("data-scale", availWidth/textWidth); // sets the data attribute, which is read in the next step 
} 

function chordWidth(dFromCenter, radius) { 
    if (dFromCenter > radius) return Number.NaN; 
    if (dFromCenter === radius) return 0; 
    if (dFromCenter === 0) return radius * 2; 

    // a^2 + b^2 = c^2 
    var a = dFromCenter; 
    var c = radius; 
    var b = Math.sqrt(Math.pow(c, 2) - Math.pow(a, 2)); // 1/2 of chord length 

    return b * 2; 
} 
関連する問題