D3.js

2015-06-02 11 views
7

में स्वचालित पाठ आकार के साथ ज़ूम करने योग्य सर्किल पैकिंग मैं दो माइक के उदाहरणों को मर्ज करने की कोशिश कर रहा हूं: Zoomable Circle Packing + Automatic Text SizingD3.js

यह प्रारंभ में शीर्ष स्तर पर प्रदर्शित होने पर काम करता है। हालांकि, यदि आप अगले स्तर पर ज़ूम इन करते हैं, तो फोंट सही ढंग से आकार में नहीं आते हैं।

मुझे यकीन नहीं है कि मुझे रूपांतरण को संशोधित करने या फ़ॉन्ट आकार की गणना करने वाले भाग को संशोधित करने की आवश्यकता है या नहीं। 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"); 

"विज़" मंडली में शामिल सबसे बड़ी उप सर्कल पर क्लिक करना समस्या दिखाता है:

यहाँ मेरी codepen है।

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

+1

ऐसा लगता है कि यह ठीक काम कर रहा है मेरे लिए लग रहा है शीर्ष स्तर पर वी को छोड़कर सभी वर्गों के लिए। यहां तक ​​कि दृष्टि के बच्चे भी ठीक हैं। क्या वीस के बारे में कुछ अलग है? – couchand

+0

कुछ उप-मंडल ठीक दिखाई देते हैं, लेकिन समस्या देखने के लिए "Vis" सर्कल में कुछ उप-मंडलियों पर क्लिक करें। https://dl.dropboxusercontent.com/u/3040414/vis-circle.png –

+0

यहां तक ​​कि आपके डेटा में कोई "Vis" सर्कल नहीं है ... यदि मैं आपके जेएस को खोजता हूं तो वहां कोई "Vis" नहीं है। तुम्हारी किस बारे में बोलने की इच्छा थी? –

उत्तर

3

पहले, चक्र के लिए एक आईडी देना यहाँ मैं चक्र आईडी के रूप में पाठ का नाम दे रहा हूँ ताकि मैं पाठ और पाठ नाम के माध्यम से अपने सर्कल लिंक कर सकते हैं।

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

संक्रमण zoom(d) function की पूरी पर हैं (यानी आप एक सर्कल पर क्लिक करें और यह ज़ूम जब) एक समय समाप्ति समारोह जो पाठ फ़ॉन्ट ज़ूम के आधार पर आकार पुनर्गणना जाएगा जोड़ें।

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

आपका calculateTextFontSize समारोह इस तरह दिखेगा (मैं असली डोम त्रिज्या का उपयोग कर रहा फ़ॉन्ट आकार की गणना करने के):

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

उत्तर के लिए धन्यवाद। टाइमआउट का दिलचस्प उपयोग। मैंने इस उत्तर को सही के रूप में चिह्नित किया क्योंकि यह मेरे द्वारा प्रदान किए गए भड़काने वाले नमूना डेटा के साथ काम करता है। दुर्भाग्य से यह मेरे वास्तविक डेटा के लिए 100% काम नहीं कर रहा है जो बड़ा है। मुझे संदेह है कि इसे समय के साथ करना है। –

+0

यदि आपको अपने डेटासेट को साझा करने में कोई समस्या नहीं है, तो क्या आप इसे गिस्ट पर उपलब्ध करा सकते हैं, मुझे एक नज़र दिखाई देगी। वर्तमान उदाहरण के साथ इसे एकीकृत करना। – Cyril

+0

@Cyril आपको बहुत धन्यवाद, यह एक बड़ी मदद थी .. एक और चीज है जो मैं करना चाहता हूं, मैं पत्ती नोड्स में चित्र दिखाना चाहता था, मैं रूट डेटा से इसे पास कर रहा हूं लेकिन मैं इसे कैसे प्रदर्शित कर सकता हूं वृत्त? – void

1

मैं भी आप के रूप में एक ही समस्या थी और मैं इस एक कोशिश की और यह मेरे लिए काम करता है।

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

+0

मैं इसे लागू करने की कोशिश कर रहा हूं, हालांकि, मेरे शीर्ष-स्तरीय नोड्स के लिए बाउंडिंग बॉक्स 0 है , 0 जो स्केल = अनंत बनाता है। क्या आपके पास कहीं ऑनलाइन कोड कोड है (github, jsfiddle, codepen)? –