2015-12-07 12 views
6

Ben bağlantıları boyunca metin etiketleriyle bir D3 kuvvet yönettiği görselleştirme oluşturduk. İçinde bulunduğum bir sorun, bağlantılar, kaynak düğümlerinin solunda olduğunda baş aşağı görünen bu etiketlerdir. Ben nasılsa her yolun geçerli açısını belirlemek gerekir biliyorum ve daha sonra setgöster D3 bağlantı metni sağ tarafı yukarı

var nodes = flatten(data); 
var links = d3.layout.tree().links(nodes); 

var path = vis.selectAll('path.link') 
    .data(links, function(d) { 
    return d.target.id; 
    }); 

path.enter().insert('svg:path') 
    .attr({ 
    class: 'link', 
    id: function(d) { 
     return 'text-path-' + d.target.id; 
    }, 
    'marker-end': 'url(#end)' 
    }) 
    .style('stroke', '#ccc'); 

var linkText = vis.selectAll('g.link-text').data(links); 

linkText.enter() 
    .append('text') 
    .append('textPath') 
     .attr('xlink:href', function(d) { 
     return '#text-path-' + d.target.id; 
     }) 
     .style('text-anchor', 'middle') 
     .attr('startOffset', '50%') 
     .text(function(d) {return d.target.customerId}); 

: Burada Örnek: öylesine gibi yolunu ve metni konumlandırmak

enter image description here

kod görünüyor metin pozisyonu buna göre, ama nasıl emin değilim. Orada yol http://blockbuilder.org/MattDionis/5f966a5230079d9eb9f4 aşağıda cevabı bana var

yaklaşık% 90: İşte

bu konuda dayalı bir bloğa bir bağlantıdır.

enter image description here

: Burada

enter image description here

... ve aşağıda cevabını ipuçlarını kullanarak nasıl göründüğünü edilir: İşte benim özgün görselleştirme artık bir çift basamaklı sayısından daha metinle neye benzediği

metin "yukarı sağ taraftaki" Şimdi ise Yani, artık yay takip etmektedir. Çizdiğiniz

+0

https://stackoverflow.com/questions/8663844/add-text-label-onto-links-in-d3-force-directed-graph adresine bakın. –

cevap

6

yay ortasında kendi teğet tam metin taban çizgisinin yönü olacak şekildedir VE aynı zamanda iki ağaç düğümlerini ayıran vektör ile eş doğrusaldır.

Biz sorunu çözmek için kullanabilirsiniz.

matematik Biraz gereklidir. İlk olarak, yatay eksene göre olan bir vektör v açısını döndüren bir işlev tanımlayalım:

function xAngle(v) { 
    return Math.atan(v.y/v.x) + (v.x < 0 ? Math.PI : 0); 
} 

Daha sonra, her kene de, en yerinde metin eksi taban çizgisine açısını dönmesine izin verin.Birincisi, birkaç fayda fonksiyonları: eklendi resmi::

example result

düzenlemek 2

function isFiniteNumber(x) { 
    return typeof x === 'number' && (Math.abs(x) < Infinity); 
} 

function isVector(v) { 
    return isFiniteNumber(v.x) && isFiniteNumber(v.y); 
} 

bulunabiliyor ve sonra da tick işlevinde,

linkText.attr('transform', function (d) { 
    // Checks just in case, especially useful at the start of the sim 
    if (!(isVector(d.source) && isVector(d.target))) { 
     return ''; 
    } 

    // Get the geometric center of the text element 
    var box = this.getBBox(); 
    var center = { 
     x: box.x + box.width/2, 
     y: box.y + box.height/2 
    }; 

    // Get the tangent vector 
    var delta = { 
     x: d.target.x - d.source.x, 
     y: d.target.y - d.source.y 
    }; 

    // Rotate about the center 
    return 'rotate(' 
     + (-180/Math.PI*xAngle(delta)) 
     + ' ' + center.x 
     + ' ' + center.y 
     + ')'; 
    }); 
}); 

düzenlemek eklemek Kavisli yaylar yerine düz çizgilerle (sadece <text> yerine) <text><textPath>, bununla linkText ilgilendiren tick fonksiyonunun bir kısmının yerini alabilecek:

linkText.attr('transform', function(d) { 
    if (!(isVector(d.source) && isVector(d.target))) { 
     return ''; 
    } 

    // Get the geometric center of this element 
    var box = this.getBBox(); 
    var center = { 
     x: box.x + box.width/2, 
     y: box.y + box.height/2 
    }; 

    // Get the direction of the link along the X axis 
    var dx = d.target.x - d.source.x; 

    // Flip the text if the link goes towards the left 
    return dx < 0 
     ? ('rotate(180 ' 
      + center.x 
      + ' ' + center.y 
      + ')') 
     : ''; 
}); 

ve bu ne elde ediyoruz:

rotated text

Bildirimi nasıl Link, daha fazla sağa işaret etmek için, daha fazla sola işaret etmek üzere, metin çevrilir.

Buradaki sorun, metnin bağlantının altında kalmasıdır.

linkText.attr('transform', function(d) { 
    if (!(isVector(d.source) && isVector(d.target))) { 
     return ''; 
    } 

    // Get the geometric center of this element 
    var box = this.getBBox(); 
    var center = { 
     x: box.x + box.width/2, 
     y: box.y + box.height/2 
    }; 

    // Get the vector of the link 
    var delta = { 
     x: d.target.x - d.source.x, 
     y: d.target.y - d.source.y 
    }; 

    // Get a unitary vector orthogonal to delta 
    var norm = Math.sqrt(delta.x * delta.x + delta.y * delta.y); 
    var orth = { 
     x: delta.y/norm, 
     y: -delta.x/norm 
    }; 

    // Replace this with your ACTUAL font size 
    var fontSize = 14; 

    // Flip the text and translate it beyond the link line 
    // if the link goes towards the left 
    return delta.x < 0 
     ? ('rotate(180 ' 
      + center.x 
      + ' ' + center.y 
      + ') translate(' 
      + (orth.x * fontSize) + ' ' 
      + (orth.y * fontSize) + ')') 
     : ''; 
}); 

ve şimdi sonuç aşağıdaki gibidir:

enter image description here

Gördüğünüz gibi, metin, çizgi üstünde güzel bile bağlantıyı oturur şöyle That sabitlenebilir sola doğru işaret eder.

Son olarak, yayları tutarken ve bir tarafı sağa doğru eğriltirken, sorunu çözmek için iki adet <textPath> öğesi oluşturmanız gerektiğini düşünüyorum. Biri source'dan target'a, diğeri ise ters yöne gitmek için. Bağlantı sağa doğru (delta.x >= 0) ve ikincisi ise sola (delta.x < 0) doğru gittiğinde ilkini kullanırsınız ve sonuç daha güzel görünür ve kodun orijinalden daha karmaşık olması gerekmez. Sadece biraz daha mantık ekledi.

+0

Teşekkür ederiz! Bu harika bir açıklamaydı ve yolun yaklaşık% 90'ını aldım. Kalan sorunu vurgulamak için orijinal soruma birkaç resim daha ekledim. Metin etiketinin her yayda oturmasını hedefliyorum. – MattDionis

+0

Düşüncelerden dün ikinci sayımla ilgili bir cevap gördüm, ama şimdi gitmiş gibi görünüyor. Hala bunun üzerinde çalışıyorum, eğer bu basit bir tasarım kararı olduğu için bu daha kolay çözülürse, kavisli bağlantıları düz çizgilere çevirmeye istekliyim. – MattDionis

+0

@MattDionis Peki, kavisli olan metni önemsemediğinizi söylemiş olduğunuza sevindim, çünkü bu gereksinim, çözümün başarılması için daha zor bir yol olurdu. Metnin düz olmasına izin verirseniz kod daha basit hale gelir ve bu sayede yukarıdaki ilk çözümden daha basittir, çünkü dönüşe gerek yoktur. Sadece 'delta' vektörü sola ("delta.x <0") gittiğinde metni çevirin. Kodu yazabildiğim zaman yazacağım. – jrsala