2017-03-03 13 views
0

D3.js v3からバージョン4に移行しようとしています。私はchangelogをレビューしてすべての機能を更新しましたが、対角関数が削除されたので、ソースノードからターゲットノードへのパスをレンダリングできません。D3.jsでソースからターゲットへのパスをレンダリングできません。v3からv4に移行します。

私はPython ScriptでHTMLとd3.jsを使って生成したParse Treeを使用しています。 Pythonのスクリプトは、ここでそれがD3.jsバージョン3

function drawTree(){ 
 
var margin = {top: 20, right: 120, bottom: 20, left: 120}, 
 
    width = 1060 - margin.right - margin.left, 
 
    height = 600 - margin.top - margin.bottom; 
 
    
 
var i = 0, 
 
    duration = 750,// animation duration 
 
    root;// stores the tree structure in json format 
 

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

 
var edge_weight = d3.scale.linear() 
 
\t \t \t \t \t .domain([0, 100]) 
 
        .range([0, 100]); 
 

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

 
// adding the svg to the html structure 
 
var svg = d3.select("div#viz").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 + ")"); 
 

 
var treeData = 
 
    { 
 
    "name": "Grandparent", 
 
    "size" : 100, 
 
    "children": [ 
 
     { 
 
     "name": "Parent A", 
 
     "size": 70, 
 
     "children": [ 
 
      { "name": "Son of A", 
 
      "size" : 30, 
 
      "children": [ 
 
       { "name": "grandson of A", 
 
       "size" : 3}, 
 
       { "name": "grandson 2 of A", 
 
       "size" : 2}, 
 
       { "name": "grandson 3 of A", 
 
       "size" : 5}, 
 
       { "name": "grandaughter of A", 
 
       "size" : 20, 
 
       "children": [ 
 
        { "name": "great-grandson of A", 
 
        "size" : 15}, 
 
        { "name": "great-grandaughter of A", 
 
        "size" : 5} 
 
       ] 
 
       } 
 
      ], 
 
      }, 
 
      { "name": "Daughter of A" , 
 
     \t \t "size" : 40 
 
      } 
 
     ] 
 
     }, 
 
     { "name": "Parent B", 
 
     "size" : 30 }], 
 
    \t }; 
 
    
 
    
 
    edge_weight.domain([0,treeData.size]); 
 
    
 
// Assigns parent, children, height, depth 
 
root = treeData; 
 
root.x0 = height/2; 
 
root.y0 = 0; 
 
    
 
    root.children.forEach(collapse); 
 
    update(root); 
 

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

 
/** 
 
* Updates the node. 
 
* cloppases and expands the node bases on the structure of the source 
 
* all 'children' nodes are expanded and '_children' nodes collapsed 
 
* @param {json structure} source 
 
*/ 
 
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 + ")"; 
 
    }) 
 
    .on('click', click); 
 

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

 
    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", function(d){ console.log(">>>>>>>>", d);return edge_weight(d.size/2);}) 
 
     .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… 
 
    // 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("stroke-width", function(d){ 
 
     \t return 1; 
 
     }) 
 
     .attr("d", function(d) { 
 
     var o = {x: source.x0, y: source.y0}; 
 
     return diagonal({source: o, target: o}); 
 
     }) 
 
     .attr("stroke", function(d){ 
 
     \t return "lavender";}); 
 

 
    // Transition links to their new position. 
 
    link.transition() 
 
     .duration(duration) 
 
     .attr("d", function(d){ 
 
     /* calculating the top shift */ 
 
     var source = {x: d.source.x - edge_weight(calculateLinkSourcePosition(d)), y: d.source.y}; 
 
     var target = {x: d.target.x, y: d.target.y}; 
 
     return diagonal({source: source, target: target}); 
 
     }) 
 
     .attr("stroke-width", function(d){ 
 
     \t return edge_weight(d.target.size); 
 
     }); 
 

 
// 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 diagonal({source: o, target: o}); 
 
     }) 
 
     .remove(); 
 

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

 
/** 
 
* Calculates the source y-axis position of the link. 
 
* @param {json structure} link 
 
*/ 
 
function calculateLinkSourcePosition(link) { 
 
\t targetID = link.target.id; 
 
\t var childrenNumber = link.source.children.length; 
 
\t var widthAbove = 0; 
 
\t for (var i = 0; i < childrenNumber; i++) 
 
\t { 
 
\t \t if (link.source.children[i].id == targetID) 
 
\t \t { 
 
\t \t \t // we are done 
 
\t \t \t widthAbove = widthAbove + link.source.children[i].size/2; 
 
\t \t \t break; 
 
\t \t }else { 
 
\t \t \t // keep adding 
 
\t \t \t widthAbove = widthAbove + link.source.children[i].size 
 
\t \t } 
 
\t } 
 
\t return link.source.size/2 - widthAbove; 
 
} 
 

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

 
/* 
 
* Collapses the node d and all the children nodes of d 
 
* @param {node} d 
 
*/ 
 
function collapse(d) { 
 
    if (d.children) { 
 
    d._children = d.children; 
 
    d._children.forEach(collapse); 
 
    d.children = null; 
 
    } 
 
} 
 

 
/* 
 
* Collapses the node in the tree 
 
*/ 
 
function collapseAll() { 
 
\t root.children.forEach(collapse); 
 
\t update(root); 
 
} 
 

 
/* 
 
* Expands the node d and all the children nodes of d 
 
* @param {node} d 
 
*/ 
 
function expand(d) { 
 
\t if (d._children) { 
 
\t \t d._children = null; 
 
\t } 
 
\t if (d.children) { 
 
\t \t d.children.forEach(expand); 
 
\t } 
 
\t 
 
} 
 
/* 
 
* Expands all the nodes in the tree 
 
*/ 
 
function expandAll() { 
 
\t root.children.forEach(expand); 
 
\t update(root); 
 
} 
 
}
.node { 
 
    cursor: pointer; 
 
} 
 

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

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

 
.link { 
 
    fill: none; 
 
    /*stroke: steelblue;*/ 
 
    opacity: 0.3; 
 
    /*stroke-width: 1.5px;*/ 
 
} 
 

 
#levels{ 
 
    margin-left: 120px; 
 
}
<!DOCTYPE html> 
 
<meta charset="utf-8"> 
 
<body onLoad="drawTree()"> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.0.0/d3.min.js"></script> 
 

 
<button type="button" onclick="collapseAll()">Collapse All</button> 
 
<button type="button" onclick="expandAll()">Expand All</button> 
 
<div id="viz"></div> 
 
</body>

で実行されていて、ここでは私の知る限りV4の移行となったようですが、HMTLドキュメントを生成します。

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

 
var i = 0, 
 
    duration = 750, // animation duration 
 
    root; // stores the tree structure in json format 
 

 

 
// declares a tree layout and assigns the size 
 
var treemap = d3.tree().size([height, width]); 
 

 
var edge_weight = d3.scaleLinear() 
 
    .domain([0, 100]) 
 
    .range([0, 100]); 
 

 

 
// Creates a curved (diagonal) path from parent to the child nodes 
 
function diagonal(s, d) { 
 

 
    path = `M ${s.y} ${s.x} 
 
      C ${(s.y + d.y)/2} ${s.x}, 
 
       ${(s.y + d.y)/2} ${d.x}, 
 
       ${d.y} ${d.x}` 
 

 
    return path 
 
} 
 

 
// adding the svg to the html structure 
 
var svg = d3.select("div#viz").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 + ")"); 
 

 

 
var treeData = { 
 
    "name": "Grandparent", 
 
    "size": 100, 
 
    "children": [{ 
 
     "name": "Parent A", 
 
     "size": 70, 
 
     "children": [{ 
 
      "name": "Son of A", 
 
      "size": 30, 
 
      "children": [{ 
 
       "name": "grandson of A", 
 
       "size": 3 
 
      }, 
 
      { 
 
       "name": "grandson 2 of A", 
 
       "size": 2 
 
      }, 
 
      { 
 
       "name": "grandson 3 of A", 
 
       "size": 5 
 
      }, 
 
      { 
 
       "name": "grandaughter of A", 
 
       "size": 20, 
 
       "children": [{ 
 
        "name": "great-grandson of A", 
 
        "size": 15 
 
       }, 
 
       { 
 
        "name": "great-grandaughter of A", 
 
        "size": 5 
 
       } 
 
       ] 
 
      } 
 
      ], 
 
     }, 
 
     { 
 
      "name": "Daughter of A", 
 
      "size": 40 
 
     } 
 
     ] 
 
    }, 
 
    { 
 
     "name": "Parent B", 
 
     "size": 30 
 
    } 
 
    ], 
 
}; 
 

 

 
edge_weight.domain([0, treeData.size]); 
 

 
// Assigns parent, children, height, depth 
 
root = d3.hierarchy(treeData, function(d) { 
 
    return d.children; 
 
}); 
 
root.x0 = height/2; 
 
root.y0 = 0; 
 

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

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

 
/** 
 
* Updates the node. 
 
* cloppases and expands the node bases on the structure of the source 
 
* all 'children' nodes are expanded and '_children' nodes collapsed 
 
* @param {json structure} source 
 
*/ 
 
function update(source) { 
 
    // Assigns the x and y position for the nodes 
 
    var treeData = treemap(root); 
 

 
    // Compute the new tree layout. 
 
    var nodes = treeData.descendants(), 
 
    links = treeData.descendants().slice(1); 
 

 
    // 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 + ")"; 
 
    }) 
 
    .on('click', click); 
 

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

 
    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 = nodeEnter.merge(node); 
 

 
    nodeUpdate.transition() 
 
    .duration(duration) 
 
    .attr("transform", function(d) { 
 
     return "translate(" + d.y + "," + d.x + ")"; 
 
    }); 
 

 
    nodeUpdate.select("circle") 
 
    .attr("r", function(d) { 
 
     return edge_weight(d.data.size/2); 
 
    }) 
 
    .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.id; 
 
    }); 
 
    //.data(links, function(d) { return d.target.id; }); 
 

 
    // Enter any new links at the parent's previous position. 
 
    var linkEnter = link.enter().insert('path', "g") 
 
    .attr("class", "link") 
 
    .attr('d', function(d) { 
 
     console.log("linkEnter", d); 
 
     var o = { 
 
     x: source.x, 
 
     y: source.y 
 
     } 
 
     console.log("o", o); 
 
     return diagonal(o, o) 
 
    }) 
 
    .attr("stroke", function(d) { 
 
     return "cyan"; 
 
    }); 
 

 
    // Transition links to their new position. 
 
    link.transition() 
 
    .duration(duration) 
 
    .attr("d", function(d) { 
 
     console.log("lala", d); 
 
     /* calculating the top shift */ 
 
     var source = { 
 
     x: d.x - edge_weight(calculateLinkSourcePosition(d)), 
 
     y: d.y 
 
     }; 
 
     var target = { 
 
     x: d.parent.x, 
 
     y: d.parent.y 
 
     }; 
 
     return diagonal({ 
 
     source: source, 
 
     target: target 
 
     }); 
 
    }) 
 
    .attr("stroke-width", function(d) { 
 
     return edge_weight(d.target.size); 
 
    }); 
 

 
    // 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 diagonal({ 
 
     source: o, 
 
     target: o 
 
     }); 
 
    }) 
 
    .remove(); 
 

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

 
/** 
 
* Calculates the source y-axis position of the link. 
 
* @param {json structure} link 
 
*/ 
 
function calculateLinkSourcePosition(link) { 
 
    targetID = link.target.id; 
 
    var childrenNumber = link.source.children.length; 
 
    var widthAbove = 0; 
 
    for (var i = 0; i < childrenNumber; i++) { 
 
    if (link.source.children[i].id == targetID) { 
 
     // we are done 
 
     widthAbove = widthAbove + link.source.children[i].size/2; 
 
     break; 
 
    } else { 
 
     // keep adding 
 
     widthAbove = widthAbove + link.source.children[i].size 
 
    } 
 
    } 
 
    return link.source.size/2 - widthAbove; 
 
} 
 

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

 
/* 
 
* Collapses the node d and all the children nodes of d 
 
* @param {node} d 
 
*/ 
 
function collapse(d) { 
 
    if (d.children) { 
 
    d._children = d.children; 
 
    d._children.forEach(collapse); 
 
    d.children = null; 
 
    } 
 
} 
 

 
/* 
 
* Collapses the node in the tree 
 
*/ 
 
function collapseAll() { 
 
    root.children.forEach(collapse); 
 
    update(root); 
 
} 
 

 
/* 
 
* Expands the node d and all the children nodes of d 
 
* @param {node} d 
 
*/ 
 
function expand(d) { 
 
    if (d._children) { 
 
    d.children = d._children; 
 
    d._children = null; 
 
    } 
 
    if (d.children) { 
 
    d.children.forEach(expand); 
 
    } 
 

 
} 
 
/* 
 
* Expands all the nodes in the tree 
 
*/ 
 
function expandAll() { 
 
    root.children.forEach(expand); 
 
    update(root); 
 
}
.node { 
 
    cursor: pointer; 
 
} 
 

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

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

 
.link { 
 
    fill: none; 
 
    /*stroke: steelblue;*/ 
 
    opacity: 0.3; 
 
    /*stroke-width: 1.5px;*/ 
 
} 
 

 
#levels { 
 
    margin-left: 120px; 
 
}
<body> 
 
    <script src="http://d3js.org/d3.v4.min.js"></script> 
 
    <button type="button" onclick="collapseAll()">Collapse All</button> 
 
    <button type="button" onclick="expandAll()">Expand All</button> 
 
    <div id="viz"></div> 
 
</body>

私はちょうどブラインドほとんどの場合だと、あなたはすぐに私が間違って何をしたかがわかりますが、私は...今、しばらくの間、この見つめてきた

助けをあらかじめありがとう!

+0

私の回答を複製(https://stackoverflow.com/q/40845121/5768908)でチェックしてください。同様の方法が導入されました。 –

答えて

1

私は現在、同様のプロジェクトに自分自身を仕事とこれはかなり役に立つことができ考え出してる...ちょうど、親/子ノードに到達するためにいくつかのマイナーなパスを調整するために必要な、あなたが本当に接近していたようです。..

基本的に "ソース"は "親"になり、 "ターゲット"はありません。コメントアウトされた行がv3であり、その下にv4アップデートがあるほとんどのアップデートを見ることができます。例:

link.target.id --> link.id 
link.source.children.length --> link.parent.children.length 
link.source.size --> link.parent.data.size 

その他の雑多な更新もコード全体であります。私が完全に働くことができなかったことの1つは、「Expand All/Collapse All」ボタンでした。私はそこに出口リンクに行うことができるものだが、容疑者https://jsfiddle.net/jufra0b2/

:OK動作するように思われる「すべて展開」、それだけでリンクパスを残しているようだ「すべてを折りたたむ」..

は、ここでの作業フィドルですわからない。とにかくそれは正しい方向への一歩です。あなたは残りの部分を確認することを願って.. ..

関連する問題