Newer
Older
indexation / public / js / force-directed-graph-svg.js
"use strict";
(function() {
    var lastTime = 0;
    var vendors = ['webkit', 'moz'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        window.cancelAnimationFrame =
          window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
    }

    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function(callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function() { callback(currTime + timeToCall); },
              timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };

    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
}());

function initGraph(url, corpus) {
  var loc = window.location.pathname,
    dir = loc.substring(0, loc.lastIndexOf('/')),
    corpus = JSON.parse(corpus);

  var svg = d3.select("svg"),
    sketch = svg.append("g"),
    container = d3.select("#container"),
    color = d3.scaleOrdinal(d3.schemeCategory20),
    width = +container.attr("width"),
    height = +container.attr("height");

  var zoom = d3.zoom()
    .scaleExtent([-100, 100])
    .on('zoom', zoomFn);

  function zoomFn() {
    sketch.attr('transform', 'translate(' + d3.event.transform.x + ',' + d3.event.transform.y + ') scale(' + d3.event.transform.k + ')');
  }
  svg.call(zoom);

  var simulation = d3.forceSimulation()
    .force("link", d3.forceLink().id(function(d) {
      return d.id;
    }))
    .force("charge", d3.forceManyBody())
    .force("center", d3.forceCenter(width / 2, height / 2));

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

    var edges = [],
      nodes = [];
    for (var i = 0; i < graph.nodes.length; i++) {
      nodes.push(i);
    }
    for (var i = 0; i < graph.links.length; i++) {
      var edge = graph.links[i];
      edge.weight = edge.value;
      edges.push(edge);
    }

    // Create the "community"
    var community = jLouvain().nodes(nodes).edges(edges),
      res = community();

    // Affect community for each node
    for (var key in res) {
      graph.nodes[nodes[key]].group = res[key];
    }

    var deleted_links = {},
      selectedLinks = graph.links.filter(function(d) {
        var res = (d.value >= 5);
        if (!res) {
          deleted_links[d.source] = deleted_links[d.source] + 1 || 1;
          deleted_links[d.target] = deleted_links[d.target] + 1 || 1;
        }
        return res;
      }),
      selectedNodes = graph.nodes.filter(function(d) {
        d.value = d.value - (deleted_links[d.id] || 0);
        var res = (d.value > 0);
        return res;
      });

    var link = sketch
      // .append("g")
      // .attr("class", "links")
      .selectAll("line")
      .data(selectedLinks)
      .enter().append("line")
      .attr("class", "links")
      .attr("stroke-width", function(d) {
        return 3;
        // return d.value;
      });

    link.append("title")
      .text(function(d) {
        return d.value;
      });

    var node = sketch
      // .append("g")
      // .attr("class", "nodes")
      .selectAll("circle")
      .data(selectedNodes)
      .enter()
      .append("circle")
      .attr("class", "nodes")
      .attr("r", function(d) {
        return 7;
        // return 10 * d.specificity;
      })
      .attr("fill", function(d) {
        return color(d.group);
      })
      // .call(d3.drag()
      //   .on("start", dragstarted)
      //   .on("drag", dragged)
      //   .on("end", dragended))
      .on("click", function(d) {
        window.open('/' + corpus.in + '/' + d.data.id + '.txt');
      })
      .on("mouseover", function(d) {
        d3.select("#subtitle")
          .style("opacity", 1)
          .text(() => {
            return d3.select(this).selectAll("title").text();
          });
        d3.select(this)
          .attr("r", 14);
      })
      .on("mouseleave", function(d) {
        d3.select("#subtitle")
          .style("opacity", 0);
        d3.select(this)
          .attr("r", 7);
      });

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

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

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

    function ticked() {
      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) {
          return d.x;
        })
        .attr("cy", function(d) {
          return 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(0);
    d.fx = null;
    d.fy = null;
  }
}