Javascript 在Rails 4上实现力定向图的鱼眼(使用d3.js)

Javascript 在Rails 4上实现力定向图的鱼眼(使用d3.js),javascript,jquery,ruby-on-rails,d3.js,Javascript,Jquery,Ruby On Rails,D3.js,我正在尝试使用d3.js在力定向图上实现鱼眼失真。出于某种原因,失真作用于链接,而不是节点。这可能是由于节点是g元素造成的,但我不确定。任何帮助都将不胜感激 var svg, node, link; function make_graph() { // Clear out the div first $("#display_graph svg:first").remove(); // Sets size var width = 960, height = 500

我正在尝试使用d3.js在力定向图上实现鱼眼失真。出于某种原因,失真作用于链接,而不是节点。这可能是由于节点是g元素造成的,但我不确定。任何帮助都将不胜感激

var svg, node, link;

function make_graph() {

  // Clear out the div first
  $("#display_graph svg:first").remove();

  // Sets size
  var width = 960,
      height = 500;

  // Maps groups to colors
  var color = d3.scale.category20();

  // Select the div and append a svg
  svg = d3.select("#display_graph").append("svg")
      .attr("width", width)
      .attr("height", height);

  // Pull json from graph
  var json_from_db = $('.graph_json').data('json');
  var json_nodes = json_from_db.nodes
  var json_links = json_from_db.links

  // Sets up the force directed graph
  var charge_val = $('#charge').val();
  var link_distance_val = $('#link_distance').val();
  var force = d3.layout.force()
      .charge(charge_val)
      .linkDistance(link_distance_val)
      .size([width, height])
      .nodes(json_nodes)
      .links(json_links)
      .start();

  link = svg.selectAll(".link")
      .data(json_links)
    .enter().append("line")
      .attr("class", "link")
      .style("stroke-width", function(d) { return Math.sqrt(d.value); });

  var font_size_px = $('#font_size').val();
  node = svg.selectAll(".node")
      .data(json_nodes)
    .enter().append("g")
      .attr("class", "node")
      .style("font-size", font_size_px)
      .call(force.drag);

  var radius = $('#radius').val();
  node.append("circle")
      .attr("r", radius)
      .style("fill", function(d) { return color(d.group); });

  node.append("text")
      .attr("dx", 12)
      .attr("dy", ".35em")
      .text(function(d) { return d.name; });

  force.on("tick", function() {
    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("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
  });

  $('#fisheye_btn').click( function() {
    var glyph_color = $(this).css('color');
    // original color is white
    orig_color = 'rgb(255, 255, 255)';

    if (glyph_color == orig_color) {
      $(this).css('color', 'orange');
    } else {
      $(this).css('color', orig_color);
    };
  });

};

function make_fisheye() {
  var fisheye = d3.fisheye.circular()
    .radius(200)
    .distortion(2);

  svg.on("mousemove", function() {
    fisheye.focus(d3.mouse(this));

    node.each(function(d) { d.fisheye = fisheye(d); })
        .attr("cx", function(d) { return d.fisheye.x; })
        .attr("cy", function(d) { return d.fisheye.y; })
        .attr("r", function(d) { return d.fisheye.z * 4.5; });

    link.attr("x1", function(d) { return d.source.fisheye.x; })
        .attr("y1", function(d) { return d.source.fisheye.y; })
        .attr("x2", function(d) { return d.target.fisheye.x; })
        .attr("y2", function(d) { return d.target.fisheye.y; });
  });
}
最后,我希望用户能够通过单击按钮打开或关闭失真。谢谢你的帮助

我更新了代码。我现在可以通过点击按钮打开或关闭失真

// Make force directed graph on button click
$(document).ready( function() {
  $("#refresh_btn").click( function() {
    make_graph();
  });
});

// Turn on and off fisheye distortion
$(document).ready( function() {
  $('#fisheye_btn').click( function() {
    var glyph_color = $(this).css('color');
    // original color is white
    orig_color = 'rgb(255, 255, 255)';

    if (glyph_color == orig_color) {
      $(this).css('color', 'orange');
      make_graph();
      make_fisheye();
    } else {
      $(this).css('color', orig_color);
      make_graph();
    };
  });
});

var svg, node, link;

function make_graph() {

  // Clear out the div first
  $("#display_graph svg:first").remove();

  // Sets size
  var width = 960,
      height = 500;

  // Maps groups to colors
  var color = d3.scale.category20();

  // Select the div and append a svg
  svg = d3.select("#display_graph").append("svg")
      .attr("width", width)
      .attr("height", height);

  // Pull json from graph
  var json_from_db = $('.graph_json').data('json');
  var json_nodes = json_from_db.nodes
  var json_links = json_from_db.links

  // Sets up the force directed graph
  var charge_val = $('#charge').val();
  var link_distance_val = $('#link_distance').val();
  var force = d3.layout.force()
      .charge(charge_val)
      .linkDistance(link_distance_val)
      .size([width, height])
      .nodes(json_nodes)
      .links(json_links)
      .start();

  link = svg.selectAll(".link")
      .data(json_links)
    .enter().append("line")
      .attr("class", "link")
      .style("stroke-width", function(d) { return Math.sqrt(d.value); });

  var font_size_px = $('#font_size').val();
  node = svg.selectAll(".node")
      .data(json_nodes)
    .enter().append("g")
      .attr("class", "node")
      .style("font-size", font_size_px)
      .call(force.drag);

  var radius = $('#radius').val();
  node.append("circle")
      .attr("r", radius)
      .style("fill", function(d) { return color(d.group); });

  node.append("text")
      .attr("dx", 12)
      .attr("dy", ".35em")
      .text(function(d) { return d.name; });

  force.on("tick", function() {
    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("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
  });
};

function make_fisheye() {
  var fisheye = d3.fisheye.circular()
    .radius(200)
    .distortion(2);

  svg.on("mousemove", function() {
    fisheye.focus(d3.mouse(this));

    node.each(function(d) { d.fisheye = fisheye(d); })
        .attr("cx", function(d) { return d.fisheye.x; })
        .attr("cy", function(d) { return d.fisheye.y; })
        .attr("r", function(d) { return d.fisheye.z * 4.5; });

    link.attr("x1", function(d) { return d.source.fisheye.x; })
        .attr("y1", function(d) { return d.source.fisheye.y; })
        .attr("x2", function(d) { return d.target.fisheye.x; })
        .attr("y2", function(d) { return d.target.fisheye.y; });
  });
}
不幸的是,我仍然有问题,只是链接被扭曲。节点实际上是g元素,我越来越相信这可能是问题所在。有没有一种方法可以使用d3.js选择g元素内部的元素?我很惊讶鱼眼失真并不仅仅传递给g元素内部的元素。也许我猜错了

新代码

现在,点击一个按钮,节点和链接都扭曲了!代码如下:

// Global variables
var svg, node, link; 
var fisheye_on = false;

// Make force directed graph on button click
$(document).ready( function() {
  $("#refresh_btn").click( function() {
    // Make sure fisheye is turned off
    $('#fisheye_btn').css('color', 'white');
    fisheye_on = false;
    make_graph();
  });
});

// Turn on and off fisheye distortion
$(document).ready( function() {
  $('#fisheye_btn').click( function() {
    var glyph_color = $(this).css('color');
    // original color is white
    orig_color = 'rgb(255, 255, 255)';

    if (glyph_color == orig_color) {
      $(this).css('color', 'orange');
      fisheye_on = true;
      make_graph();
    } else {
      $(this).css('color', orig_color);
      fisheye_on = false;
      make_graph();
    };
  });
});


function make_graph() {

  // Clear out the div first
  $("#display_graph svg:first").remove();

  // Sets size
  var width = 960,
      height = 500;

  // Maps groups to colors
  var color = d3.scale.category20();

  // Select the div and append a svg
  svg = d3.select("#display_graph").append("svg")
      .attr("width", width)
      .attr("height", height);

  // Pull json from graph
  var json_from_db = $('.graph_json').data('json');
  var json_nodes = json_from_db.nodes
  var json_links = json_from_db.links

  // Sets up the force directed graph
  var charge_val = $('#charge').val();
  var link_distance_val = $('#link_distance').val();
  var force = d3.layout.force()
      .charge(charge_val)
      .linkDistance(link_distance_val)
      .size([width, height])
      .nodes(json_nodes)
      .links(json_links)
      .start();

  link = svg.selectAll(".link")
      .data(json_links)
    .enter().append("line")
      .attr("class", "link")
      .style("stroke-width", function(d) { return Math.sqrt(d.value); });

  var font_size_px = $('#font_size').val();
  node = svg.selectAll(".node")
      .data(json_nodes)
    .enter().append("g")
      .attr("class", "node")
      .style("font-size", font_size_px)
      .call(force.drag);

  var radius = $('#radius').val();
  node.append("circle")
      .attr("r", radius)
      .style("fill", function(d) { return color(d.group); });

  node.append("text")
      .attr("dx", 12)
      .attr("dy", ".35em")
      .text(function(d) { return d.name; });

  if (fisheye_on == false) {

    force.on("tick", function() {
      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("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
    });

  } else {

    var fisheye = d3.fisheye.circular()
      .radius(200)
      .distortion(2);

    svg.on("mousemove", function() {
      fisheye.focus(d3.mouse(this));

      node.each(function(d) { d.fisheye = fisheye(d); });

      node.selectAll("circle")
          .attr("cx", function(d) { return d.fisheye.x - d.x; })
          .attr("cy", function(d) { return d.fisheye.y - d.y; })
          .attr("r", function(d) { return d.fisheye.z * 4.5; });

      node.selectAll("text")
          .attr("dx", function(d) { return d.fisheye.x - d.x; })
          .attr("dy", function(d) { return d.fisheye.y - d.y; });

      link.attr("x1", function(d) { return d.source.fisheye.x; })
          .attr("y1", function(d) { return d.source.fisheye.y; })
          .attr("x2", function(d) { return d.target.fisheye.x; })
          .attr("y2", function(d) { return d.target.fisheye.y; });
    });
  };
};
不幸的是,我遇到了另一个问题。当应用失真时,似乎存在初始滞后。节点先变形,然后链接变形。不确定是什么原因造成的。有什么提示吗

Public JSFiddle

我设法在公共JSFIDLE中复制了该问题:


要生成图形,只需单击“生成图形”。单击“鱼眼”将打开和关闭鱼眼扭曲。问题是首先节点变形,然后链接随之变形。我希望节点和链接同时被扭曲。任何帮助都将不胜感激

请发布一个完整的工作示例好吗?在您的
make_fisheye
功能中,尝试
节点。选择All(“圆圈”)。每个…
都有效。不过我遇到了另一个问题。很快就会发布代码。如果您能在JSFIDLE或类似的东西上放置一个完整的工作示例,这将有所帮助。
var svg, node, link;

function make_graph() {

  // Clear out the div first
  $("#display_graph svg:first").remove();

  // Sets size
  var width = 960,
      height = 500;

  // Maps groups to colors
  var color = d3.scale.category20();

  // Select the div and append a svg
  svg = d3.select("#display_graph").append("svg")
      .attr("width", width)
      .attr("height", height);

  // Pull json from graph
  var json_from_db = $('.graph_json').data('json');
  var json_nodes = json_from_db.nodes
  var json_links = json_from_db.links

  // Sets up the force directed graph
  var charge_val = $('#charge').val();
  var link_distance_val = $('#link_distance').val();
  var force = d3.layout.force()
      .charge(charge_val)
      .linkDistance(link_distance_val)
      .size([width, height])
      .nodes(json_nodes)
      .links(json_links)
      .start();

  link = svg.selectAll(".link")
      .data(json_links)
    .enter().append("line")
      .attr("class", "link")
      .style("stroke-width", function(d) { return Math.sqrt(d.value); });

  var font_size_px = $('#font_size').val();
  node = svg.selectAll(".node")
      .data(json_nodes)
    .enter().append("g")
      .attr("class", "node")
      .style("font-size", font_size_px)
      .call(force.drag);

  var radius = $('#radius').val();
  node.append("circle")
      .attr("r", radius)
      .style("fill", function(d) { return color(d.group); });

  node.append("text")
      .attr("dx", 12)
      .attr("dy", ".35em")
      .text(function(d) { return d.name; });

  force.on("tick", function() {
    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("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
  });

  $('#fisheye_btn').click( function() {
    var glyph_color = $(this).css('color');
    // original color is white
    orig_color = 'rgb(255, 255, 255)';

    if (glyph_color == orig_color) {
      $(this).css('color', 'orange');
    } else {
      $(this).css('color', orig_color);
    };
  });

};

function make_fisheye() {
  var fisheye = d3.fisheye.circular()
    .radius(200)
    .distortion(2);

  svg.on("mousemove", function() {
    fisheye.focus(d3.mouse(this));

    node.each(function(d) { d.fisheye = fisheye(d); })
        .attr("cx", function(d) { return d.fisheye.x; })
        .attr("cy", function(d) { return d.fisheye.y; })
        .attr("r", function(d) { return d.fisheye.z * 4.5; });

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