2017-11-08 11 views
1

グラフsvgの上にマウスを置いて上下にスクロールさせたときに、力向グラフを拡大したいと思います。私は本当にこれを行う方法がわかりません。私はsvgを選択して、擬似ズームのようなsvgのサイズを増減することができましたが、私が探しているものではないsvgのサイズと位置が変わります。 svgをスクロールすると、ノードとリンクを選択してサイズを大きくするにはどうすればよいですか?ズームを追加する方法のおかげ力のグラフをd3で拡大するにはどうすればいいですか?

var svg = d3.select("svg") 
     , 
    width = +svg.attr("width"), 
    height = +svg.attr("height"); 

var color = d3.scaleOrdinal(d3.schemeCategory20); 

var forceParameter = 30 
    maxDistanceParameter = 100; 

var simulation = d3.forceSimulation() 
    .force("link", d3.forceLink().distance(forceParameter).strength(.5)) 
    .force("charge", d3.forceManyBody().distanceMax(maxDistanceParameter)) 
    .force("center", d3.forceCenter(width/2, height/2)); 

var linkMap = d3.map(); 

d3.json("courses.json", function(error, graph) { 
    if (error) throw error; 

    var nodes = graph.nodes, 
     nodeById = d3.map(nodes, function(d) { return d.id; }), 
     links = graph.links, 
     bilinks = []; 

    links.forEach(function(link) { 
     var s = link.source = nodeById.get(link.source), 
      t = link.target = nodeById.get(link.target), 
      i = {}; // intermediate node 
     nodes.push(i); 
     links.push({source: s, target: i}, {source: i, target: t}); 
     bilinks.push([s, i, t]); 
    }); 

    //Populate the map that keeps track of how many links a class node has 
    links.forEach(function(d){ 
     if(linkMap.has(d.source.id)) 
      linkMap.set(d.source.id, linkMap.get(d.source.id) + .5); 
     else 
      linkMap.set(d.source.id, .5); 
    }); 

    var link = svg.selectAll(".link") 
     .data(bilinks) 
     .enter().append("path") 
     .attr("class", "link"); 

    var node = svg.selectAll(".node") 
     .data(nodes.filter(function(d) { return d.id; })) 
     .enter().append("circle") 
     .attr("class", "node") 
     //Size the node differently if the node represents a department 
     .attr("r", function(d){ 
      return (d.group === "Department") ? 15 : (5 * linkMap.get(d.id)); 
     }) 
     //Color the node differently if the node represents a department 
     .attr("fill", function(d) { 
      return (d.group === "Department") ? "#3B4656" : color(d.group); 
     }) 
     //Color the node outline differently if the node represents a department 
     .style("stroke", function(d){ 
      return (d.group === "Department") ? "black" : "white"; 
     }) 
     //When a node is clicked, all nodes that are more than 1 link away are faded out 
     .on("click", function(d){ 
      d3.event.stopPropagation(); 
      onNodeClick(this, d, links); 
     }) 
     .call(d3.drag() 
      .on("start", dragstarted) 
      .on("drag", dragged) 
      .on("end", dragended)); 


    //Unfade all nodes when whitespace is clicked 
    svg.on("click", function(){ 
     d3.selectAll(".node") 
      .attr("opacity", "1"); 
    }); 

    //Force parameter buttons 
    d3.select("#forcesPlus") 
     .on("click", function(){ 
      updateParameters(1); 
    }); 
    d3.select("#forcesMinus") 
     .on("click", function(){ 
      updateParameters(-1); 
    }); 

    node.append("title") 
     .text(function(d) { return d.id; }); 

    simulation 
     .nodes(nodes) 
     .on("tick", ticked); 

    simulation.force("link") 
     .links(links); 

    function ticked() { 
     link.attr("d", positionLink); 
     node.attr("transform", positionNode); 
    } 

    /** Updates the force parameters of the graph 
    * 
    * @param sign - Determines if we are increasing or decreasing the parameters 
    */ 
    function updateParameters(sign){ 
     //Increase the passive jiggle of the nodes so that they visually update (expand/contract) 
     //when the parameter gets changed 
     simulation.alphaTarget(.1); 

     forceParameter += sign * 20; 
     maxDistanceParameter += sign * 20; //Need to update the max distance so that the 
              //links can actually get longer 

     simulation.nodes(nodes); 
     simulation.force("link", d3.forceLink().distance(forceParameter)) 
        .force("charge", d3.forceManyBody().distanceMax(maxDistanceParameter)); 

     simulation 
      .nodes(nodes) 
      .on("tick", ticked); 

     simulation.force("link") 
      .links(links); 

     //Hack so that the buttons don't break when the nodes settle down to a stand-still. 
     //Not sure why the buttons don't update once they are still, but this solves it. 
     //Need the nodes to move in order to see the change in force parameter. 
     setTimeout(function(){ 
      simulation.alphaTarget(.01); 
     }, 2000); 
    } 

}); 

//Fades out any nodes that are not connected to the clicked node 
function onNodeClick(click, selectedNode, linkList){ 
    var linkedNodes = d3.set(); 

    linkList.forEach(function(v){ 
     //If the node clicked is the link's source, add the link's target 
     if (selectedNode.id === v.source.id){ 
      linkedNodes.add(v.target.id); 
     } 
     //If the node clicked is the link's target, add the link's source 
     else if (selectedNode.id === v.target.id){ 
      linkedNodes.add(v.source.id); 
     } 
    }); 

    d3.selectAll(".node") 
     .attr("opacity", function(d){ 
      if (linkedNodes.has(d.id)) 
       return "1"; 
      else 
       return "0.1"; 
    }); 

    d3.select(click) 
     .attr("opacity", "1"); 
} 

function positionLink(d) { 
    return "M" + d[0].x + "," + d[0].y 
     + "S" + d[1].x + "," + d[1].y 
     + " " + d[2].x + "," + d[2].y; 
} 

function positionNode(d) { 
    return "translate(" + d.x + "," + d.y + ")"; 
} 

function dragstarted(d) { 
    if (!d3.event.active) simulation.alphaTarget(0.3).restart(); 
    d.fx = d.x, d.fy = d.y; 
} 

function dragged(d) { 
    d.fx = d3.event.x, d.fy = d3.event.y; 
} 

function dragended(d) { 
    if (!d3.event.active) simulation.alphaTarget(.01); 
    d.fx = null, d.fy = null; 
} 

function linkDistance(d){ 
    console.log(d); 
} 

答えて

1

例としては、ここで見つけることができます:https://coderwall.com/p/psogia/simplest-way-to-add-zoom-pan-on-d3-js

技術的には、何をやっていることは、SVGのルートで<g>要素を追加し、その後で自動的にズーム/パンを処理するために、D3を伝えていますその要素の翻訳とスケーリングしたがって、すべてのコンテンツ(ノードとリンク)も(ここでは:zoomContainer):その要素の内側に追加する必要があります

var zoomContainer = svg.call(d3.zoom().on("zoom", function() { 
    zoomContainer.attr("transform", d3.event.transform) 
})) 
.append("g"); 

... 

var link = zoomContainer.selectAll(".link") 
       .data(bilinks) 
       .enter().append("path") 
... 

var node = zoomContainer.selectAll(".node") 
       .data(nodes.filter(function(d) { return d.id; })) 
       .enter().append("circle") 
... 

https://jsfiddle.net/fseeyphe/

+0

は明確な説明のためにありがとうございました!よく働く。 – awoh

関連する問題