2015-06-02 14 views
7

Tôi đang cố hợp nhất hai ví dụ của Mike: Zoomable Circle Packing + Automatic Text Sizing.Đóng gói vòng tròn có thể phóng to có định kích thước văn bản tự động trong D3.js

Nó hoạt động khi ban đầu được hiển thị ở cấp cao nhất. Tuy nhiên, nếu bạn phóng to đến cấp độ tiếp theo, phông chữ không được định kích thước chính xác.

Tôi không chắc liệu tôi có cần sửa đổi biến đổi hay sửa đổi phần tính toán kích thước phông chữ hay không.

Dưới đây là codepen tôi: 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"); 

Nhấp vào tiểu vòng tròn lớn nhất trong "vis" vòng tròn minh họa vấn đề.

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

+1

Có vẻ với tôi như nó làm việc tốt cho tất cả các phần ngoại trừ vis ở cấp cao nhất. Ngay cả trẻ em của vis là ok. Có điều gì khác về vis? – couchand

+0

Một số vòng kết nối phụ có vẻ tốt, nhưng nhấp vào một số vòng tròn con trong vòng kết nối "Vis" để xem sự cố. https://dl.dropboxusercontent.com/u/3040414/vis-circle.png –

+0

Ngay cả trong dữ liệu của bạn không có vòng kết nối "Vis" ... nếu tôi tìm kiếm JS của bạn thì không có "Vis". Bạn đang nói về cái gì vậy? –

Trả lời

3

đầu tiên đưa ra một id để vòng tròn, ở đây tôi cho tên văn bản như ID vòng tròn để tôi có thể liên kết các văn bản và hình tròn của nó thông qua tên văn bản.

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(); 
    }); 

On chuyển đổi hoàn toàn của zoom(d) function (nghĩa là khi bạn click vào một vòng tròn và nó phóng) thêm một chức năng thời gian chờ mà sẽ tính toán lại kích thước font chữ dựa trên 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) 

chức năng calculateTextFontSize của bạn sẽ trông như thế này (tôi đang sử dụng bán kính DOM thực để tính toán kích thước phông chữ): Mã Làm việc

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; 
    } 
    } 
} 

here

+0

Cảm ơn câu trả lời. Thú vị sử dụng thời gian chờ. Tôi đã đánh dấu câu trả lời này là chính xác vì nó hoạt động với dữ liệu mẫu bùng phát mà tôi đã cung cấp. Thật không may nó không làm việc 100% cho dữ liệu thực tế của tôi lớn hơn. Tôi nghi ngờ nó đã làm với thời gian. –

+0

nếu bạn không có bất kỳ vấn đề trong việc chia sẻ tập dữ liệu của bạn, bạn có thể làm cho nó có sẵn trên gist tôi sẽ có một cái nhìn. tích hợp nó với ví dụ hiện tại. – Cyril

+0

@Cyril Cảm ơn bạn rất nhiều, đó là một trợ giúp lớn .. Có một điều nữa tôi muốn làm, tôi muốn hiển thị hình ảnh trong các nút lá, tôi chuyển nó từ dữ liệu gốc nhưng làm cách nào tôi có thể hiển thị hình tròn? – void

1

Tôi cũng có cùng một vấn đề như bạn và tôi đã cố gắng này và nó làm việc cho tôi.

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

+0

Tôi đang cố gắng áp dụng điều này, tuy nhiên, hộp giới hạn cho các nút cấp cao nhất của tôi là 0 , 0 làm cho scale = Infinity. Bạn có mã làm việc ở đâu đó trực tuyến không (github, jsfiddle, codepen)? –

Các vấn đề liên quan