2012-11-02 22 views
49

Sonunda D3'ü öğrenme sürecindeyim ve bir yanıt bulamadığım bir sorunla karşılaştım. Sorularımın kütüphane ile deyimsel olarak düşünmediğimden veya şu anda habersiz olduğum bir prosedürden kaynaklandığından emin değilim. Ayrıca Haziran ayında web ile ilgili şeyler yapmaya başladığımı da belirtmeliyim, bu yüzden javascript için oldukça yeni.D3, iç içe ekler ve veri akışı

Kullanıcıya, ilgili görüntülere sahip yiyeceklerin listesini veren bir araç oluşturduğumuzu varsayalım. Ayrıca, her bir liste öğesinin başka bir görünüme bağlanabilmesi için benzersiz bir kimlik tarafından etiketlenmesi gereken ek kısıtlamalara ekleyelim. Bunu çözmek için ilk sezgilerim, her biri kendi 'un kendi kimliğine sahip bir liste oluşturmaktır. Burada her bir div, kendi <p> ve <img>'dur. Ortaya çıkan HTML görünümü aşağıdaki gibi olacaktır:

<div id="chocolate"> 
    <p>Chocolate Cookie</p> 
    <img src="chocolate.jpg" /> 
</div> 
<div id="sugar"> 
    <p>Sugar Cookie</p> 
    <img src="sugar.jpg" /> 
</div> 

gibi bu araç için veri bireysel JSON görünen bir JSON dizisi, içinde:

{ "label": "sugar", "text": "Sugar Cookie", "img": "sugar.jpg" } 

elde edebilirim için bir yol var mı Birinde HTML düştü? bir div ekleme bir taban durumunda başlayarak, kod aşağıdaki gibi olabilir: Artık

d3.select(containerId).selectAll('div')               
    .data(food) 
    .enter().append('div') 
    .attr('id', function(d) { return d.label; }); 

, ne olmuş bir <p> ile <div> eklemeye ne dersiniz? (1) nasıl div eleman verileri alırım, ve (2) nasıl birden çocukları ekleyebilirsiniz: Ben bu konuda iki sorun bakın

d3.select(containerId).selectAll('div')               
    .data(food) 
    .enter().append('div') 
    .attr('id', function(d) { return d.label; }) 
     .append('p').text('somethingHere'); 

Ama: My orijinal bir düşünce böyle bir şey yapmak oldu bir bildirici zincirde aynı ebeveyn? img'a ekleyeceğim üçüncü adımı yapmanın bir yolunu düşünemiyorum.

http://bost.ocks.org/mike/nest/'a işaret eden başka bir gönderide yuvalanmış seçimden bahsetmiştim. Ama iç içe geçmiş bir seçimdir ve bu yüzden bu durum için uygun/idiyomik olan üç parçanın eklerini parçalara ayırarak mı? Ya da bu yapıyı bir deklarasyon zincirinde şekillendirmek için iyi yapılandırılmış bir yol var mı? https://github.com/mbostock/d3/wiki/Selections'da belirtilen alt seçimlerin bir yolu olabilir gibi görünüyor, ancak bu hipotezi test etmek için dil ile yeterince tanıdık değilim. kavramsal düzeyde kaynaktan

, bu üç nesneleri ( div, p ve img) daha bir grup yerine ayrı ayrı öğeler olarak ele alınır, ve kodu da yansıyan halinde çok daha iyi olurdu.

cevap

69

Birden çok alt öğeyi zincirleme bir komut içinde ekleyemezsiniz. Üst seçimi bir değişkene kaydetmeniz gerekir. İstediğin bu yapmalıyım: Sen p veya img gibi bir alt öğe Onun ailesine bağlı olduğu verilere erişimi nasıl olur merak edildi http://jsfiddle.net/UNjuP/

:

var data = [{ "label": "chocolate", "text": "Chocolate Cookie", "img": "chocolate.jpg" }, 
     { "label": "sugar", "text": "Sugar Cookie", "img": "sugar.jpg" }]; 

var diventer = d3.select("body").selectAll("div") 
    .data(data) 
    .enter().append("div") 
    .attr("id", function(d) { return d.label; }); 

diventer.append("p") 
    .text(function(d) { return d.text; }); 

diventer.append("img") 
    .attr("src", function(d) { return d.img; });​ 

çalışma keman bakın. Yeni bir öğe eklediğinizde veriler otomatik olarak ebeveynden miras alınır. Bu, p ve img öğelerinin, ebeveyn div ile aynı veriye bağlı olacağı anlamına gelir.

Bu veri çoğaltma, append yöntemi için benzersiz değildir.Aşağıdaki selection yöntemleriyle olur: append, insert ve select. selection.append için örneğin

:

selection.append (ad)

mevcut seçim, her bir parça son çocuk belirtilen ada sahip yeni bir elemanı ekler. Eklenen öğeleri içeren yeni bir seçim döndürür. Her yeni öğe, alt seçimleri için seçilenle aynı şekilde mevcut öğelerin verisini miras alır. İsim, sabit olarak belirtilmelidir, ancak geleceğinde varolan öğelerin eklenmesine izin verebiliriz veya bir işlevi adı dinamik olarak üretir.

Bir şey net değilse, detaylar hakkında soru sormaya çekinmeyin.


Sen selection.each yöntemini kullanarak bir değişken seçimi kaydetmeden birden çok alt öğeleri ekleyebilirsiniz

DÜZENLEME. Daha sonra da doğrudan ebeveynden verilere erişebilir:

var data = [{ "label": "chocolate", "text": "Chocolate Cookie", "img": "chocolate.jpg" }, 
     { "label": "sugar", "text": "Sugar Cookie", "img": "sugar.jpg" }]; 

d3.select("body").selectAll("div") 
    .data(data) 
    .enter().append("div") 
    .attr("id", function(d) { return d.label; }) 
    .each(function(d) { 
     d3.select(this).append("p") 
      .text(d.text); 
     d3.select(this).append("img") 
      .attr("src", d.img); 
    }); 
+6

Fantastik! Çocuk düğümlerinin aynı veri kapsamına sahip olduğunu fark etmemiştim. Açıklama için teşekkürler :) –

+3

'selection.each' kullanılarak yükseltilmiştir. – Yawar

+2

Gruplandırılmış (veya iç içe) düğümler eklemek için 'selection.each' işlevini kullanırsanız, güncelleştirme adımı için 'selection.each' özelliğini de kullanmayı unutmayın (ve belki de çıkış adımı için). – npdoty

3

Bu nautat's answer temelde farklı değil, ama ben kodu yerine güncelleme seçim kaydederek biraz temizleyici yapılabilir düşünüyorum , seçimini girerek, numarasını almayı gerektiren bir işlemden (çevreleyen alanı ekleyerek) numarasını girin.

() seçim alanına bir öğe eklediğinizde veya eklediğinizde, daha sonra çalışabileceğiniz güncelleştirme seçimine eklenir.

: Bu, daha sonra girmek seçimle bir div ekleyin ve güncelleme seçimle eklemek zaman sonra, girdiğiniz seçiminde eklendi div içinde ekleme olacağım, veri katılabileceği anlamına gelir

var cookies = [ 
 
    { "label": "sugar", "text": "Sugar Cookie", "img": "sugar.jpg" }, 
 
    { "label": "chocolate", "text": "Chocolate Cookie", "img": "chocolate.jpg" }]; 
 

 
var cookie = d3.select("#cookie-jar").selectAll().data(cookies); 
 
cookie.enter().append("div"); 
 
cookie.append("p").text(function(d){ return d.text }); 
 
cookie.append("img").attr("src",function(d){ return d.img });
#cookie-jar div { border: solid 1px black; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 
 
<div id="cookie-jar"></div>

19

Yine, önemli ölçüde farklı değil, ancak herhangi bir vari saklamak gerekmez benim tercih edilen yöntem 'çağrısı'

var data = [{ "label": "chocolate", "text": "Chocolate Cookie", "img": "chocolate.jpg" }, 
     { "label": "sugar", "text": "Sugar Cookie", "img": "sugar.jpg" }]; 

d3.select("body").selectAll("div") 
    .data(data) 
    .enter().append("div") 
    .attr("id", function(d) { return d.label; }) 
    .call(function(parent){ 
    parent.append('p').text(function(d){ return d.text; }); 
    parent.append('img').attr("src", function(d) { return d.img; });​ 
    }); 

kullanmak olacaktır Eğer başka bir yerde benzer bir yapı kullanmak istiyorsanız, ables ve aranan işlevi faksa ayırabilirsiniz.

+0

bunu seviyorum!Bu benim için çok kolay iç içe nesneleri – ptim

+0

güncelleme işlemek için bu benim yukarıdaki verilerden çok daha iyi uyuyor, çünkü hiçbir veri yok ve sadece bir iç değişken kullanmaksızın bir ebeveyn yeniden kullanmak istiyorum, teşekkürler sen! –