プロジェクトでjQueryをD3に置き換える方法

ビジュアライゼーションまたはインタラクティブページを作成するとき、jQueryとD3の組み合わせをよく使用します。 さらに、D3は主に使用され、jQueryからDOMを操作するための小さな関数セットを使用します。



また、D3には強力な機能(ajaxのセレクターとラッパー)がありますが、jQueryの一部の機能が見落とされがちです。 どこでもD3を使用してjQueryを置き換える方法を示します。 その結果、コードが簡素化され、プロジェクトのボリュームが減少し、異なるアプローチを混在させることはありませんが、D3で一般的な機能を使用します。



最初に、これら2つのライブラリがどのように収束するかを見てみましょう。 これは、すでにjQueryを知っており、D3を学びたい人にとって便利です。



類似点



セレクター


どちらのライブラリも使いやすいが、機能が豊富なセレクターに基づいています。



jQuery



$('.foo').addClass('foobar'); $('.foo').removeClass('foobar');
      
      







D3



 d3.selectAll('.foo').classed('foobar', true); d3.selectAll('.foo').classed('foobar', false);
      
      







スタイルと属性を管理する


jQuery



 $('.foo').attr('data-type', 'foobar'); $('.foo').css('background', '#F00');
      
      







D3



 d3.selectAll('.foo').attr('data-type', 'foobar'); d3.selectAll('.foo').style('background', '#F00');
      
      







アヤックス


構文は若干異なりますが、D3とjQueryの両方に優れたラッパーがあります

アヤックス。



jQuery



 $.getJSON('http://url-to-resource.json', doSomething); $.ajax({ url: 'http://url-to-resource.txt', dataType: 'text', type: 'GET', success: doSomething });
      
      







D3



 d3.json('http://url-to-resource.json', doSomething); d3.text('http://url-to-resource.txt', doSomething);
      
      







クラス管理


多くの場合、スタイルを切り替えるなど、DOM要素クラスを管理する必要があります。



jQuery



 $('.foo').addClass('foobar'); $('.foo').removeClass('foobar');
      
      







D3



 d3.selectAll('.foo').classed('foobar', true); d3.selectAll('.foo').classed('foobar', false);
      
      







追加と追加


特に入力データを視覚化する場合、子ノードの挿入は重要な機能です。 これは簡単でシンプルです。



jQuery



 $('.foo').append('<div/>'); $('.foo').prepend('<div/>');
      
      







D3



 d3.selectAll('.foo').append('div'); d3.selectAll('.foo').insert('div');
      
      







イベント追跡


選択した要素のイベントを追跡するために、同じ構文が設計されています。



jQuery



 $('.foo').on('click', clickHandler);
      
      







D3



 d3.selectAll('.foo').on('click', clickHandler);
      
      







アイテムを削除する


DOMからアイテムを削除する必要がある場合があります。 方法は次のとおりです。



jQuery



 $('.foo').remove();
      
      







D3



 d3.selectAll('.foo').remove();
      
      







サブセット選択


幅広い選択から子を選択できます



jQuery



 $('.foo').find('.bar');
      
      







D3



 d3.selectAll('.foo').selectAll('.bar');
      
      







コンテンツ管理


次の関数を使用して、DOMノードのコンテンツを変更できます。



jQuery



 $('.foo').text('Hello World!'); $('.foo').html('<div class="bar">Hello</div>');
      
      







D3



 d3.selectAll('.foo').text('Hello World!'); d3.selectAll('.foo').html('<div class="bar">Hello</div>');
      
      







違い



ここで、jQueryにはあるがD3にはない機能を検討してください。 それらのそれぞれについて、それを置き換える簡単なソリューションと、より一般的な使用例があります。これは、ブランド化されたD3チェーンを使用して、アプリケーションのどこにでも役立つ可能性があります。



イベントとカスタムイベント(トリガーイベントとカスタムイベント)のアクティブ化


jQueryの利点の1つは、イベントを処理する便利さです。 ページ上の任意のアイテムのカスタムイベントをトリガーまたは追跡できます。 たとえば、ドキュメントのデータを使用してカスタムイベントを開始し、コードで追跡できます。



 // $(document).on('dataChange', function(evt, data) { //do something with evt and data console.log(data.newData); }); //  $(document).trigger('dataChange', { newData: 'Hello World!' });
      
      







D3では、これは直接サポートされていませんが、常にこの動作を実現できます。 シンプルなオプション(ハンドラーでd3.eventが必要ない場合):



 // d3.select(document).on('dataChange', function(data) { console.log(d3.event); //null console.log(data.newData); }); //  d3.select(document).on('dataChange')({ newData: 'Hello World!' });
      
      







より一般的なアプローチは、d3オブジェクトに関数を追加して、任意の選択で使用できるようにすることです。



 d3.selection.prototype.trigger = function(evtName, data) { this.on(evtName)(data); }
      
      







この関数をD3に追加すると、jQueryに似たトリガー関数を取得でき、次のように使用できます。



 d3.select(document).on('dataChange', function(data) { console.log(data); });
      
      







d3.select(document).trigger( 'dataChange'、{newData: 'HelloWorld!'});



後()および前()


jQueryを使用すると、選択範囲内のすべての要素の直後に要素を挿入できます。 コードを考慮してください:



 <ul> <li>List</li> <li>List</li> <li>List</li> </ul>
      
      







次の簡単なコードを使用して、リスト内の各アイテムの後に新しいアイテムを挿入できます。



 $('li').after('<li>Item</li>');
      
      







そして、ここに私たちが得るものがあります:



 <ul> <li>List</li> <li>Item</li> <li>List</li> <li>Item</li> <li>List</li> <li>Item</li> </ul>
      
      







D3では、選択のすべての要素を調べて、JavaScriptで追加する必要があります。



 d3.selectAll('li').each(function() { var li = document.createElement('li'); li.textContent = 'Item'; this.parentNode.insertBefore(li, this.nextSibling); })
      
      







最良のオプションは、タグ名に基づいて要素を追加し、作成された要素の新しい選択を返し、編集できるようにする汎用関数を作成することです。



 d3.selection.prototype.after = function(tagName) { var elements = []; this.each(function() { var element = document.createElement(tagName); this.parentNode.insertBefore(element, this.nextSibling); elements.push(element); }); return d3.selectAll(elements); }
      
      







コードに次を追加することにより、jQueryとほぼ同じ方法でafter()関数を使用できます。



 d3.selectAll('li') .after('li') .text('Item') //      - 
      
      







before()関数はほとんど同じように見えますが、唯一の違いは選択の前に要素が挿入されることです。



 d3.selection.prototype.before = function(tagName) { var elements = []; this.each(function() { var element = document.createElement(tagName); this.parentNode.insertBefore(element, this); elements.push(element); }); return d3.selectAll(elements); }
      
      







空()


簡単です-jQuery関数は、選択範囲内のすべての子ノードを削除します。







 $('ul').empty();
      
      







結果として:



 <ul></ul>
      
      







D3では、このために、選択した要素の内部HTMLをクリアする必要があります。



 d3.selectAll('ul').html('');
      
      







D3は、SVGでの作業によく使用されます。 この場合、innerHTMLはサポートされていないため、このコードは機能しません。 したがって、html()を呼び出さずに、すべての子ノードを選択して削除することをお勧めします。



 d3.selectAll('ul').selectAll('*').remove();
      
      







汎用コードは簡単です。 D3にはすでに独自のempty()関数があるため、jQueryで使用されているものとは異なる名前を関数に選択しました。



 d3.selection.prototype.clear = function() { this.selectAll('*').remove(); return this; }
      
      







これで、jQueryとほぼ同じ方法で選択をクリアできます。



 d3.selectAll('#foo').clear();
      
      







appendTo()


jQueryでは、この関数はD3のappend()関数とほぼ同じように機能しますが、前の選択項目を別の選択に追加します。 D3でこれを行うには、両方の選択のすべての要素を調べて、要素を相互に追加する必要があります。 選択を追加する必要があるいくつかの目標がある場合、オブジェクトを複製してjQueryに似た動作を取得する必要があります。 ここに私が得たものがあります:



 d3.selection.prototype.appendTo = function(selector) { var targets = d3.selectAll(selector), targetCount = targets[0].length, _this = this, clones = []; targets.each(function() { var currTarget = this; _this.each(function() { if(targetCount > 1) { var clone = this.cloneNode(true); currTarget.appendChild(clone); clones.push(clone); } else { currTarget.appendChild(this); } }); }); if(targetCount > 1) { this.remove(); } return clones.length > 0 ? d3.selectAll(clones) : this; }
      
      







これを使用して、DOMに複数の要素を追加できます。 作業例:



 <div class="target"></div> <div class="target"></div> <div class="foo">some element</div> <div class="foo">some other element</div>
      
      







クラス「foo」を持つすべての要素に対してappendTo()を呼び出して、それらをターゲットに追加します。



 d3.selectAll('.foo').appendTo('.target');
      
      







DOMで何が起こるか:



 <div class="target"> <div class="foo">some element</div> <div class="foo">some other element</div> </div> <div class="target"> <div class="foo">some element</div> <div class="foo">some other element</div> </div>
      
      







関数は追加された要素を返すので、それらをさらに操作できます。 たとえば、背景の変更:



d3.selectAll( '。foo')。appendTo( '。target')。style( 'background'、 '#f00');



長さ()


選択中の要素の数を知ることが役立つ場合があります。 jQueryにはlengthというプロパティがあります

 <div class=".foo"></div> <div class=".foo"></div>
      
      







 $('.foo').length; //2
      
      







D3でも同じこと:



 d3.selection.prototype.length = function() { return this[0].length; }
      
      







このコードを使用すると、次のことができます。



 d3.selectAll('.foo').length() //2
      
      







toggleClass()


既に述べたように、D3では、クラス関数を使用してクラス名を管理できます。 ただし、D3にはクラス名を切り替える機能はありません。これはjQueryでよく使用されます。 その実装は次のとおりです。



 d3.selection.prototype.toggleClass = function(className) { this.classed(className, !this.classed(className)); return this; }
      
      







eq()


複数の要素の選択をフィルタリングし、特定のインデックスを持つノードのみを選択するには、jQueryでeq()関数を使用できます。 D3に対して行うのは非常に簡単です。 インデックスに基づいて要素のサブサンプルを作成し、新しく作成された選択を返します。



 d3.selection.prototype.eq = function(index) { return d3.select(this[0][index]); }
      
      







表示()/非表示()/トグル()


ページ上の要素の可視性を変更するために使用されます。 選択した要素のスタイルを変更するだけです。 トグル()関数では、最初にこの要素が表示されているかどうかを確認する必要があります。



非表示を表示:



 d3.selection.prototype.show = function() { this.style('display', 'initial'); return this; }
      
      







非表示を非表示:



 d3.selection.prototype.hide = function() { this.style('display', 'none'); return this; }
      
      







可視性の切り替え:



 d3.selection.prototype.toggle = function() { var isHidden = this.style('display') == 'none'; return this.style('display', isHidden ? 'inherit' : 'none'); }
      
      







moveToFront()、moveToBack()


これらの機能は多くの場合D3にありませんが、jQueryとは関係ありません。 D3は、SVGでの作業によく使用されます。 同時に、SVGのHTMLとは異なり、要素の順序によって可視性が決まります。 したがって、SVGの選択を前後に移動するための十分な機能がないことがよくあります。



これを行うには、次の機能を使用してD3サンプルを展開します。



 d3.selection.prototype.moveToFront = function() { return this.each(function(){ this.parentNode.appendChild(this); }); }; d3.selection.prototype.moveToBack = function() { return this.each(function() { var firstChild = this.parentNode.firstChild; if (firstChild) { this.parentNode.insertBefore(this, firstChild); } }); };
      
      







それらの使用は非常に簡単です-svg要素を選択し、必要に応じて移動します:



 d3.select('svg rect') .moveToFront() .moveToBack();
      
      







上記が、jQueryの過剰な使用をD3の単純なソリューションに置き換えることができるプロジェクトで役立つことを願っています。 また、GitHubでは、機能が組み込まれたD3の既に拡張されたバージョンを使用できます。



All Articles