2013-08-29 15 views
9

一般的なD3選択を受け取り、その複製をSVGオブジェクトに追加することができるjavascript関数を作成したいと考えています。マイク・ボストックは、これはhere不可能であったが、それはしばらく前にあったと言っD3:選択項目の複製を追加する

<!DOCTYPE html> 
<meta charset="utf-8"> 
<body> 
<script src="http://d3js.org/d3.v3.min.js"></script> 
<script> 

svg = d3.select("body").append("svg") 
         .attr("width", 300) 
         .attr("height", 300); 

circle = svg.append("circle") 
       .attr("cx", 100) 
       .attr("cy", 100) 
       .attr("r", 20) 

function clone_selection(x, i) { 
    for (j = 0; j < i; j++) { 
    // Pseudo code: 
    // svg.append(an exact copy of x, with all the attributes) 
    } 
} 

clone_selection(circle, 5); 
</script> 

は、ここでは最低限の作業例です。

どのように達成されるかについて新しい考えがありますか?関数clone_selectionの中には、xに含まれるsvg要素が何であるか分かりません。

+0

['cloneNode'](http://www.w3schools.com/jsref/met_node_clonenode.asp)のようなものをお探しですか? –

+2

本当のクローンが必要ですか、または要素が機能しますか? – nrabinowitz

+0

両方のコメントありがとうございます。しかし、どちらも一般的なD3選択では動作しません。これについてのより多くの会話がありますが(https://github.com/mbostock/d3/pull/732#issuecomment-7390693)、selection.clone()メソッドMike Bostockの言及はまだ実装されていないと思います。 – LondonRob

答えて

9

:物事に長い道のりを行う

は、ここで作業溶液との完全なMWEです。これにより、またはtransform属性を個別に設定することができない、<use>要素を使用する際に問題が発生します。

私は素晴らしいd3jsライブラリがネイティブにこのようなものを備えていませんが、ここに私のハックだ驚い:

function clone_d3_selection(selection, i) { 
      // Assume the selection contains only one object, or just work 
      // on the first object. 'i' is an index to add to the id of the 
      // newly cloned DOM element. 
    var attr = selection.node().attributes; 
    var length = attr.length; 
    var node_name = selection.property("nodeName"); 
    var parent = d3.select(selection.node().parentNode); 
    var cloned = parent.append(node_name) 
       .attr("id", selection.attr("id") + i); 
    for (var j = 0; j < length; j++) { // Iterate on attributes and skip on "id" 
     if (attr[j].nodeName == "id") continue; 
     cloned.attr(attr[j].name,attr[j].value); 
    } 
    return cloned; 
} 
4

@nrabinowitzが<use>要素を指してくれてくれてありがとう。ここでは別の可能性があります

<!DOCTYPE html> 
<meta charset="utf-8"> 
<body> 
<script src="http://d3js.org/d3.v3.min.js"></script> 
<script> 

svg = d3.select("body").append("svg") 
      .attr("width", 300) 
      .attr("height", 300); 

circle = svg.append("circle") 
      .attr("id", "circleToClone") 
      .attr("cx", 100) 
      .attr("cy", 100) 
      .attr("r", 20) 

function clone_selection(object, i) { 
    for (j = 0; j < i; j++) { 
    // Here's the solution: 
    cloned_obj = svg.append("use") 
       .attr("xlink:href","#" + object.attr("id")); 
    } 
} 

clone_selection(circle, 5); 
</script> 
+0

これは、 'style'や' transform'属性を ''オブジェクトに適用することができないので、この方法は理想的ではないことが判明しました。つまり、最初のオブジェクトの純粋なコピーが貼り付けられています。描画ボードに戻る... – LondonRob

+0

うーん - 'fill'、' cx'、 'cy'などの属性を' use'要素に置き換えることができます。私はあなたが 'transform'を使うことができないのに驚いていますが、変換とスタイルを適用していつでも要素を' g'でラップすることができます。 – nrabinowitz

+0

これは良い答えになるはずです:)ありがとう。 –

3

この関数は、D3の選択の深いコピーを作成し、コピーされた要素の選択を返します。

function cloneSelection(appendTo, toCopy, times) { 
    toCopy.each(function() { 
    for (var i = 0; i < times; i++) { 
     var clone = svg.node().appendChild(this.cloneNode(true)); 
     d3.select(clone).attr("class", "clone"); 
    } 
    }); 
    return appendTo.selectAll('.clone'); 
} 

デモhereを参照してください。

この機能はtoCopy選択に複数の要素が含まれている場合にも機能します。

しかし、他の場所の内部要素を直接参照している場合は、すべての内部要素のクラス、idsおよびその他の属性とともに、コードを壊す可能性のあるすべてがコピーされることに注意してください。だからあなたの選択に注目してください。クローンを元のものと区別する親を持つことで、選択チェーンに言及することで、あなたを安全に保つことができます。

妥当なことは(あなたが本当にidを必要とするならば)コピーするものの外側の要素だけにidを設定することです。ここでは、関数を変更することで簡単に変更することができます:d3.select(clone).attr("class", "clone").attr("id", "clone-" + i)

0

私は自分のソリューションを開発していたのですが、私はこの質問を見つけました。これは重複を作成する方法です。

divを作成し、その上に.each()を実行し、forループを各関数に挿入します。 数字some_numberは、私に意図した重複量を与えます。

多分、貧しい人のバージョンかもしれない - 私はプロではありません。私はあなたのフィードバックを聞いています。

関連する問題