2015-09-04 164 views
0

我有一个D3折叠树的简单例子,大部分都是从教程中的例子复制和粘贴的。我试图看看是否可以用HTML替换标签正在显示的方式(即当前文本),以允许我在标签上添加一些格式。我查看了一下,发现HTML可以和svg:foreignObject一起使用,但我不太清楚在这种情况下如何做到这一点。这是我的代码。在D3中使用HTML标签

<!DOCTYPE html> 
<meta charset="utf-8"> 
<style> 

.node { 
    cursor: pointer; 
} 

.node circle { 
    fill: #fff; 
    stroke: steelblue; 
    stroke-width: 1.5px; 
} 

.node text { 
    font: 10px sans-serif; 
} 

.link { 
    fill: none; 
    stroke: #ccc; 
    stroke-width: 1.5px; 
} 

</style> 
<body> 
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script> 
<script> 

var treeData = [ 
    { 
    "name": "Rutgers", 
    "children": [ 
     { 
     "name": "Rutgers New Brunswick", 
     "children": [ 
      { 
      "name": "Rutgers School of Arts and Science", 
      }, 
      { 
      "name": "Rutgers Business School", 
      }, 
     ] 
     }, 
     { 
     "name": "Rutgers Newark", 
     }, 
    ] 
    }, 
]; 



var margin = {top: 20, right: 120, bottom: 20, left: 120}, 
    width = 960 - margin.right - margin.left, 
    height = 800 - margin.top - margin.bottom; 

var i = 0, 
    duration = 750, 
    root; 

var tree = d3.layout.tree() 
    .size([height, width]); 

var diagonal = d3.svg.diagonal() 
    .projection(function(d) { return [d.y, d.x]; }); 

var line = d3.svg.line() 
      .x(function(d){ return d.x; }) 
      .y(function(d){return d.y; }); 

    function lineData(d){ 
     var points = [ 
      {x: d.source.y, y: d.source.x}, 
      {x: d.target.y, y: d.target.x} 
     ] 
     return line(points); 
    } 


var svg = d3.select("body").append("svg") 
    .attr("width", width + margin.right + margin.left) 
    .attr("height", height + margin.top + margin.bottom) 
    .append("g") 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 


    root = treeData[0]; 
    root.x0 = height/2; 
    root.y0 = 0; 


    root.children.forEach(collapse); 
    update(root); 

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

function collapse(d) { 
    if (d.children) { 
     d._children = d.children; 
     d._children.forEach(collapse); 
     d.children = null; 
    } 
    } 

function update(source) { 

    // Compute the new tree layout. 
    var nodes = tree.nodes(root).reverse(), 
     links = tree.links(nodes); 

    // Normalize for fixed-depth. 
    nodes.forEach(function(d) { d.y = d.depth * 180; }); 

    // Update the nodes� 
    var node = svg.selectAll("g.node") 
     .data(nodes, function(d) { return d.id || (d.id = ++i); }); 

    // Enter any new nodes at the parent's previous position. 
    var nodeEnter = node.enter().append("g") 
     .attr("class", "node") 
     .attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; }) 

    nodeEnter.append("circle") 
     .attr("r", 1e-6) 
     .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; }) 
     .on("click", click); 

    nodeEnter.append("text") 
     .attr("x", function(d) { return d.children || d._children ? -10 : 10; }) 
     .attr("dy", ".35em") 
     .attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; }) 
     .text(function(d) { return d.name; }) 
     .style("fill-opacity", 1e-6); 

    // Transition nodes to their new position. 
    var nodeUpdate = node.transition() 
     .duration(duration) 
     .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; }); 

    nodeUpdate.select("circle") 
     .attr("r", 4.5) 
     .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; }); 

    nodeUpdate.select("text") 
     .style("fill-opacity", 1); 

    // Transition exiting nodes to the parent's new position. 
    var nodeExit = node.exit().transition() 
     .duration(duration) 
     .attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; }) 
     .remove(); 

    nodeExit.select("circle") 
     .attr("r", 1e-6); 

    nodeExit.select("text") 
     .style("fill-opacity", 1e-6); 

    // Update the links� 
    var link = svg.selectAll("path.link") 
     .data(links, function(d) { return d.target.id; }); 

    // Enter any new links at the parent's previous position. 
    link.enter().insert("path", "g") 
     .attr("class", "link") 
     .attr("d", function(d) { 
     var o = {x: source.x0, y: source.y0}; 
     return lineData({source: o, target: o}); 
     }); 

    // Transition links to their new position. 
    link.transition() 
     .duration(duration) 
     .attr("d", lineData); 

    // Transition exiting nodes to the parent's new position. 
    link.exit().transition() 
     .duration(duration) 
     .attr("d", function(d) { 
     var o = {x: source.x, y: source.y}; 
     return lineData({source: o, target: o}); 
     }) 
     .remove(); 

    // Stash the old positions for transition. 
    nodes.forEach(function(d) { 
    d.x0 = d.x; 
    d.y0 = d.y; 
    }); 
} 

// Toggle children on click. 
function click(d) { 
    if (d.children) { 
    d._children = d.children; 
    d.children = null; 
    } else { 
    d.children = d._children; 
    d._children = null; 
    } 
    update(d); 
} 

</script> 
</body> 
+0

我不会诉诸使用'foreignObject',除非你绝望(没有IE支持)。你需要做什么样的格式化? – Mark

+0

Mark,在每个节点将会有更多的数据,我希望以格式化的方式显示,这可能是表格数据或列表数据。是否有一种用nodeEnter.append(“html”)替换nodeEnter.append(“text”)的简单方法? – hamayoun

回答

2

这里有一个麦克例如:gist.github.com/mbostock/1424037

在这里,你的例子:jsbin.com/wibuhirohe/edit?html,output。只需用内容

nodeEnter.append("foreignObject") 
    .attr("width", 100) 
    .attr("height", 100) 
    .append("xhtml:body") 
    .style("font", "14px 'Helvetica Neue'") 
    .html("<h1>An HTML Foreign Object in SVG</h1> 
     <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. 
      Donec eu enim quam. Quisque nisi risus, sagittis quis tempor 
      nec, aliquam... 

取代HTML,如果你需要更多的风格,你可以添加一个类,像这样:

nodeEnter.append("foreignObject") 
    .attr("width", 100) 
    .attr("height", 100) 
    .attr("class", "myBeautifulText") 

然后定义上<style>

.myBeautifulText { 
    font-size: 1em; 
    ..... 
    } 
.myBeautifulText > h1 { 
     ..... 
    } 
.myBeautifulText > p { 
     ....... 
    } 

正如@马克提到它,没有IE支持