block by shimizu 06b42726331fb010c5fa566136872f22

d3.forceSimulation - center node

Full Screen

常に特定のノードをセンターに置くサンプル

Built with blockbuilder.org

index.html

<!DOCTYPE html>
<head>
  <meta charset="utf-8">
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <style>
    html, body, #graph {
      width: 100%;
      height: 100%;
    }  </style>
</head>

<body>
  <div id="graph"></div>    



  <script>
    !(function(){
      "use strict"

      var width,height
      var chartWidth, chartHeight
      var margin
      var svg = d3.select("#graph").append("svg")
      var chartLayer = svg.append("g").classed("chartLayer", true)

      main()

      function main() {
        var range = 40
        var data = {
          nodes:d3.range(0, range).map(function(d){ return {label: "l"+d ,r:~~d3.randomUniform(8, 28)(), color:"black"}}),
          links:d3.range(0, range).map(function(){ return {source:~~d3.randomUniform(range)(), target:~~d3.randomUniform(range)()} })        
        }

        //センターに指定するノードに必ずリンクをつける
        data.links.push({source:0, target:~~d3.randomUniform(range)()})
        data.links.push({source:0, target:~~d3.randomUniform(range)()})
        data.links.push({source:0, target:~~d3.randomUniform(range)()})
        data.nodes[0].color = "red";

        setSize(data)
        drawChart(data)    
      }

      function setSize(data) {
        width = document.querySelector("#graph").clientWidth
        height = document.querySelector("#graph").clientHeight

        margin = {top:0, left:0, bottom:0, right:0 }


        chartWidth = width - (margin.left+margin.right)
        chartHeight = height - (margin.top+margin.bottom)

        svg.attr("width", width).attr("height", height)


        chartLayer
          .attr("width", chartWidth)
          .attr("height", chartHeight)
          .attr("transform", "translate("+[margin.left, margin.top]+")")


      }

      function drawChart(data) {

        var simulation = d3.forceSimulation()
        .force("link", d3.forceLink().id(function(d) { return d.index }))
        .force("collide",d3.forceCollide( function(d){return d.r + 8 }).iterations(16) )
        .force("charge", d3.forceManyBody())
        .force("center", d3.forceCenter(chartWidth / 2, chartHeight / 2))
        .velocityDecay(0.4)
        .alphaTarget(0.1);

        var link = svg.append("g")
        .attr("class", "links")
        .selectAll("line")
        .data(data.links)
        .enter()
        .append("line")
        .attr("stroke", "black")

        var node = svg.append("g")
        .attr("class", "nodes")
        .selectAll("circle")
        .data(data.nodes)
        .enter().append("circle")
        .attr("cx", chartWidth / 2)
        .attr("cy", chartHeight / 2)
        .attr("r", function(d){  return d.r })
        .attr("fill", function(d){ return d.color })
        .call(d3.drag()
              .on("start", dragstarted)
              .on("drag", dragged)
              .on("end", dragended));    


        var ticked = function() {
          data.nodes[0].fx = chartWidth / 2;
          data.nodes[0].fy = chartHeight / 2;

          link
            .attr("x1", function(d) { return d.source.x; })
            .attr("y1", function(d) { return d.source.y; })
            .attr("x2", function(d) { return d.target.x; })
            .attr("y2", function(d) { return d.target.y; });

          node
            .attr("cx", function(d, i) { return d.x; })
            .attr("cy", function(d, i) { return d.y; });
        }  

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


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



        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(0);
          d.fx = null;
          d.fy = null;
        } 

      }
    }());
  </script>    
  </script>
</body>