2015-06-02 15 views
7

Próbuję połączyć dwa przykłady Mike'a: Zoomable Circle Packing + Automatic Text Sizing.Zoomable Circle Packing z automatycznym dopasowywaniem tekstu w D3.js

Działa, gdy początkowo wyświetlany jest na najwyższym poziomie. Jeśli jednak powiększysz do następnego poziomu, czcionki nie są poprawnie dobrane.

Nie jestem pewien, czy potrzebuję zmodyfikować transformację lub zmodyfikować część, która oblicza rozmiar czcionki.

Oto mój codepen: http://codepen.io/anon/pen/GJWqrL

var circleFill = function(d) { 
    if (d['color']) { 
     return d.color; 
    } else { 
     return d.children ? color(d.depth) : '#FFF'; 
    } 
} 

var calculateTextFontSize = function(d) { 
    return Math.min(2 * d.r, (2 * d.r - 8)/this.getComputedTextLength() * 11) + "px"; 
} 

var margin = 20, 
    diameter = 960; 

var color = d3.scale.linear() 
    .domain([-1, 18]) 
    .range(["hsl(0,0%,100%)", "hsl(228,30%,40%)"]) 
    .interpolate(d3.interpolateHcl); 

var pack = d3.layout.pack() 
    .padding(2) 
    .size([diameter - margin, diameter - margin]) 
    .value(function(d) { 
     return d.size; 
    }) 

var svg = d3.select("body").append("svg") 
    .attr("width", window.innerWidth) 
    .attr("height", window.innerHeight) 
    .append("g") 
    .attr("transform", "translate(" + diameter/2 + "," + diameter/2 + ")"); 

var focus = root, 
    nodes = pack.nodes(root), 
    view; 

var circle = svg.selectAll("circle") 
    .data(nodes) 
    .enter().append("circle") 
    .attr("class", function(d) { 
     return d.parent ? d.children ? "node" : "node node--leaf" : "node node--root"; 
    }) 
    .style("fill", circleFill) 
    .on("click", function(d) { 
     if (focus !== d) zoom(d), d3.event.stopPropagation(); 
    }); 

circle.append("svg:title") 
    .text(function(d) { 
     return d.name; 
    }) 

var text = svg.selectAll("text") 
    .data(nodes) 
    .enter().append("text") 
    .attr("class", "label") 
    .style("fill-opacity", function(d) { 
     return d.parent === root ? 1 : 0; 
    }) 
    .style("display", function(d) { 
     return d.parent === root ? null : "none"; 
    }) 
    .text(function(d) { 
     return d.name; 
    }) 
    .style("font-size", calculateTextFontSize) 
    .attr("dy", ".35em"); 

var node = svg.selectAll("circle,text"); 

d3.select("body") 
    .style("background", color(-1)) 
    .on("click", function() { 
     zoom(root); 
    }); 

zoomTo([root.x, root.y, root.r * 2 + margin]); 

function zoom(d) { 
    var focus0 = focus; 
    focus = d; 

    var transition = d3.transition() 
     .duration(d3.event.altKey ? 7500 : 750) 
     .tween("zoom", function(d) { 
      var i = d3.interpolateZoom(view, [focus.x, focus.y, focus.r * 2 + margin]); 
      return function(t) { 
       zoomTo(i(t)); 
      }; 
     }); 

    transition.selectAll("text") 
     .filter(function(d) { 
      return d.parent === focus || this.style.display === "inline"; 
     }) 
     .style("fill-opacity", function(d) { 
      return d.parent === focus ? 1 : 0; 
     }) 
     .each("start", function(d) { 
      if (d.parent === focus) this.style.display = "inline"; 
     }) 
     .each("end", function(d) { 
      if (d.parent !== focus) this.style.display = "none"; 
     }); 
} 

function zoomTo(v) { 
    var k = diameter/v[2]; 
    view = v; 
    node.attr("transform", function(d) { 
     return "translate(" + (d.x - v[0]) * k + "," + (d.y - v[1]) * k + ")"; 
    }); 
    circle.attr("r", function(d) { 
     return d.r * k; 
    }); 
} 

d3.select(self.frameElement).style("height", diameter + "px"); 

Kliknięcie największą sub-koło w koło "Vis" ilustruje ten problem.

https://dl.dropboxusercontent.com/u/3040414/vis-circle.png

+1

Wygląda mi na to, że wszystko działa dobrze dla wszystkich sekcji z wyjątkiem vis na najwyższym poziomie. Nawet dzieci z vis są w porządku. Czy jest coś innego na temat vis? – couchand

+0

Niektóre podkręgi wyglądają dobrze, ale kliknij niektóre z pod-okręgów w okręgu "Vis", aby zobaczyć problem. https://dl.dropboxusercontent.com/u/3040414/vis-circle.png –

+0

Nawet w twoich danych nie ma koła "Vis" ... jeśli przeszukuję twój JS, nie ma "Vis". O czym mówisz? –

Odpowiedz

3

pierwsze wydanie identyfikatora do kręgu, tutaj daję nazwę tekstu jako identyfikator okręgu tak, że można połączyć tekst i jego krąg za pomocą nazwy tekstowej.

var circle = svg.selectAll("circle") 
    .data(nodes) 
    .enter().append("circle") 
    .attr("class", function(d) { 
    return d.parent ? d.children ? "node" : "node node--leaf" : "node node--root"; 
    }) 
    .style("fill", circleFill) 
    .attr("r", function(d) { 
    return d.r; 
    }) 
    .attr("id", function(d) { 
    return d.name;//setting text name as the ID 
    }) 
    .on("click", function(d) { 
    if (focus !== d) zoom(d), d3.event.stopPropagation(); 
    }); 

Na przejściu pełnego z zoom(d) function (czyli po kliknięciu na kole i to powiększa) dodać funkcję limitu czasu, który będzie przeliczyć rozmiar czcionki tekstu w oparciu o zoom.

setTimeout(function() { 
    d3.selectAll("text").filter(function(d) { 
    return d.parent === focus || this.style.display === "inline"; 
    }).style("font-size", calculateTextFontSize);//calculate the font 
}, 500) 

Twoja funkcja calculateTextFontSize będzie wyglądać następująco (używam promień prawdziwy DOM obliczyć wielkość czcionki):

var calculateTextFontSize = function(d) { 
    var id = d3.select(this).text(); 
    var radius = 0; 
    if (d.fontsize){ 
    //if fontsize is already calculated use that. 
    return d.fontsize; 
    } 
    if (!d.computed) { 
    //if computed not present get & store the getComputedTextLength() of the text field 
    d.computed = this.getComputedTextLength(); 
    if(d.computed != 0){ 
     //if computed is not 0 then get the visual radius of DOM 
     var r = d3.selectAll("#" + id).attr("r"); 
     //if radius present in DOM use that 
     if (r) { 
     radius = r; 
     } 
     //calculate the font size and store it in object for future 
     d.fontsize = (2 * radius - 8)/d.computed * 24 + "px"; 
     return d.fontsize; 
    } 
    } 
} 

kod roboczych here

+0

Dzięki za odpowiedź. Interesujące wykorzystanie limitu czasu. Oceniłem tę odpowiedź jako poprawną, ponieważ działa ona z dostarczonymi przeze mnie przykładami próbek pochodni. Niestety nie działa w 100%, ponieważ moje rzeczywiste dane są większe. Podejrzewam, że ma to związek z czasem. –

+0

, jeśli nie masz żadnych problemów z udostępnieniem zbioru danych, możesz go udostępnić w ogólnym zarysie. integrację z bieżącym przykładem. – Cyril

+0

@Cyril Dziękuję bardzo, to była wielka pomoc. Jest jeszcze jedna rzecz, którą chcę zrobić, chciałem pokazać zdjęcia w węzłach liści, przekazuję je z danych root, ale jak mogę to pokazać w okrąg? – void

1

miałem również ten sam problem jak ty i ja próbowaliśmy to jedno i to działa na mnie.

D3.js Auto font-sizing based on nodes individual radius/diameter

+0

Próbuję zastosować to, ale ramka ograniczająca dla moich węzłów najwyższego poziomu to 0 , 0, który tworzy skalę = nieskończoność. Czy masz działający kod gdzieś online (github, jsfiddle, codepen)? –