2012-10-28 13 views
15

yay uzunluklarını nasıl hesaplanacağını:d3.js - otomatik Mike Bostock hiyerarşik kenar demetleme diyagram modifiye edilmiş bir versiyonunu yaratarak ediyorum radyal dendrogram

http://mbostock.github.com/d3/talk/20111116/bundle.html

ama bazı grupları kapsayan yay olmak için Şu anda sadece yay uzunluğunu hardcoding, ama ben dinamik olarak yapmak istiyorum

enter image description here

: böyle verilerin. Bunu nasıl başarabilirim? http://mikeheavers.com/transfers/projects/data/projects.json: Ben burada json veri yapısını gördüğüm

/* MH - USER DEFINED VARIABLES */ 
var chartConfig = { "Tension" : .85, "canvasSize" : 800, "dataFile" : "../data/projects.json", "linePadding" : 160, "textPadding" : 30, "arcPadding" : 5, "arcWidth" : 30 } 
var pi = Math.PI; 

var radius = chartConfig.canvasSize/2, 
    splines = []; 

var cluster = d3.layout.cluster() //Cluster is the diagram style, a node to link dendrogram dendrogram (tree diagram) 
    .size([360, radius - chartConfig.linePadding]); //MH - sets the size of the circle in relation to the size of the canvas 

var bundle = d3.layout.bundle(); //Bundles the node link lines so that they spread at the end but keep close initially 

var arcInner = radius - chartConfig.linePadding + chartConfig.arcPadding; 
var arcOuter = arcInner + chartConfig.arcWidth; 
var arc = d3.svg.arc().innerRadius(arcInner).outerRadius(arcOuter); 

var line = d3.svg.line.radial() 
    .interpolate("bundle") 
    .tension(chartConfig.Tension) //How tightly to bundle the lines. No tension creates straight lines 
    .radius(function(d) { return d.y; }) 
    .angle(function(d) { return d.x/180 * Math.PI; }); 

var vis = d3.select("#chart").append("svg") 
    .attr("width", radius * 2) 
    .attr("height", radius * 2) 
    .attr("class","svg") 
    .append("g") 
    .attr("class","chart") 
    .attr("transform", "translate(" + radius + "," + radius + ")"); 


d3.json(chartConfig.dataFile, function(classes) { 
    var nodes = cluster.nodes(packages.root(classes)), 
     links = packages.imports(nodes), 
     splines = bundle(links); 

    var path = vis.selectAll ("path.link") 
     .data(links) 
     .enter().append("path") 
     .attr("class", function(d){ return "link source-" + d.source.key + " target-" + d.target.key; }) 
     .attr("d", function(d,i){ return line(splines[i]); }); 

    vis.selectAll("g.node") 
     .data(nodes.filter(function(n) { return !n.children; })) 
    .enter().append("g") 
     .attr("class", "node") 
     .attr("id",function(d){ return "node-" + d.key; }) 
     .attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; }) 
    .append("text") 
     .attr("dx", function(d) { return d.x < 180 ? chartConfig.textPadding : -chartConfig.textPadding; }) //dx Moves The text out away from the lines in a positive or negative direction, depending on which side of the axis it is on 
     .attr("dy", ".31em") //moves the text up or down radially around the circle 
     .attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; }) 
     .attr("transform", function(d) { return d.x < 180 ? null : "rotate(180)"; }) 
     .text(function(d) { 
     textString = d.key; 
     textString = textString.split('_').join(' '); //MH replace underscores with spaces 
     return textString; 
     }) 
     .on("mouseover",textOver) 
     .on("mouseout",textOut); 

}); 


/* ARCS ARE HARDCODED, SHOULD BE DYNAMIC */ 

var arcData = [ 
    {aS: 0, aE: 45,rI:radius - chartConfig.linePadding + chartConfig.arcPadding,rO:radius - chartConfig.linePadding + chartConfig.textPadding-chartConfig.arcPadding} 
]; 

var arcJobsData = d3.svg.arc().innerRadius(arcData[0].rI).outerRadius(arcData[0].rO).startAngle(degToRad(1)).endAngle(degToRad(15)); 
var g = d3.select(".chart").append("svg:g").attr("class","arcs"); 
var arcJobs = d3.select(".arcs").append("svg:path").attr("d",arcJobsData).attr("id","arcJobs").attr("class","arc"); 
g.append("svg:text").attr("x",3).attr("dy",15).append("svg:textPath").attr("xlink:href","#arcJobs").text("JOBS").attr("class","arcText"); //x shifts x pixels from the starting point of the arc. dy shifts the text y units from the top of the arc 

... 

function degToRad(degrees){ 
    return degrees * (pi/180); 
} 

function updateNodes(name,value){ 
    return function(d){ 
    if (value) this.parentNode.appendChild(this); 
    vis.select("#node-"+d[name].key).classed(name,value); 
    } 
} 
+0

Merhaba, ben de aynı şeyi yapmaya çalışıyorum ... Sadece çözümü bulduysanız merak ediyorum. Ya da kaynak kodun nerede olduğunu biliyor musun? Sanırım bir yerlerde gördüm ama şimdi bulamadım ... Teşekkürler :) – wceo

+0

Hayır - ama aynı şeyi yaparsanız bir şey bulursam size bildireceğim söz veriyorum! – mheavers

+0

jsFiddle veya [Tributary] kurabilir misiniz (http://enjalot.com/tributary/) Bence zekice bir yuva uygulaması ve bir ölçek aradığınız parçaları dolduracaktır. Ne yapabileceğimi görmekten mutlu olurum ama veriler yardımcı olur! – Superboggly

cevap

13

: İşte benim geçerli kod var. İlk olarak, verileri gruplandırmak ve etiketi doğru bir şekilde eklemek için verilerinizi aşağıdaki gibi değiştirmek daha iyi olacaktır: https://raw.github.com/gist/4172625/4de3e6a68f9721d10e0068d33d1ebb9780db4ae2/flare-imports.json, hirarchical bir yapı oluşturmak için.

Arkıları çizmek için grupları kullanabiliriz.

Önce "selectAll" ile gruplar oluştururuz ve düğümlerinizi filtreleriz. Daha iyi filtrenin sonucunu doğrulamak ve duruma göre değişiklik yapmak istiyorum böylece

Sadece kontrol
var groupData = svg.selectAll("g.group") 
    .data(nodes.filter(function(d) {return (d.key=='Jobs' || d.key == 'Freelance' || d.key == 'Bayard') && d.children; })) 
.enter().append("group") 
    .attr("class", "group"); 

benim durumumda, (bizim veri yapısı bir olduğunu: Burada diğer veri grup adlarını ekleyebilirsiniz biraz farklı).

Şimdi bir grup listesi var. Sonra her grubun çocuklarına gideceğiz ve başlangıç ​​ve bitiş açısı olarak en küçük ve en büyük x'i seçeceğiz. max tarafından min değiştirerek

function findStartAngle(children) { 
    var min = children[0].x; 
    children.forEach(function(d){ 
     if (d.x < min) 
      min = d.x; 
}); 
return degToRad(min); 
} 

Ve benzer bir findEndAngle işlevi: Böyle bir işlev oluşturabilirsiniz.

Benim durumumda
svg.selectAll("g.arc") 
    .data(groupData[0]) 
.enter().append("arc") 
    .attr("d", groupArc) 
    .attr("class", "arc") 
    .append("svg:text") 
     ...; 

o groupData [0], belki bunu kontrol etmelisiniz edilir:

var groupArc = d3.svg.arc() 
    .innerRadius(arcData[0].rI) 
    .outerRadius(arcData[0].rO) 
    .startAngle(function(d){return findStartAngle(d.children);}) 
    .endAngle(function(d){return findEndAngle(d.children);}); 

Sonra 'dinamik' bir şekilde yayların oluşturabilirsiniz: Sonra Arcs' biçimini oluşturabilir senin durumun. Yaylara etiket eklemek için, seçiminizin sonucuna göre d.key veya d.name eklemeniz yeterlidir.

the arc example

tam kod burada mevcuttur: https://gist.github.com/4172625. Veritabanından json aldığımda, eğer jenerik arklara dinamik bir yol yoksa ölmüş olurum: P Hope size yardımcı olur!

+0

'findStartAngle (d.Yukarıda '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ''' '' ile tanımlanır – mccannf

+0

@mccannf Üzgünüm, benim hatam, 'function (d) {return findStartAngle (d.children);} '' – wceo

+0

Bu harika görünüyor. Bu hafta sonu test edeceğim ve her şey yolunda giderse cevabınızı kabul edeceğim. Teşekkürler! – mheavers