2

我正在尝试仅将平移(暂时不想缩放)添加到我的 D3 力导向图形可视化中。无论我尝试什么,我都会收到错误消息 - “无法读取 null 的属性‘翻译’”。我觉得好像我在设置我找到的所有示例中的内容,但有些地方不太对劲。

这是我最近的尝试。据我所知,相关代码应该在我定义 svg 的顶部,但我包括了其余部分,以防有什么我不知道的影响它。

var isiOS = false;
var agent = navigator.userAgent.toLowerCase();
  if(agent.indexOf('iphone') >= 0 || agent.indexOf('ipad') >= 0){
         isiOS = true;
  };

var h = 1000;
var w = 1000;
var width = 1500,
var height = 1500;

var default_node_color = '#FF9900';
var shining_node_color = '#fc5f05';
var text_color = 'white';
var link_color = '#666699';

var svg = d3.select("#chart").append("svg")
  .attr("width", width)
  .attr("height", height)
  .call(d3.behavior.zoom().on("zoom", function() {
    svg.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")");
  }))
  .append('g');

var g = svg.append('g');

var force = d3.layout.force()
  .gravity(0.05)
  .distance(100)
  .charge(-100)
  .size([w, h]);

d3.xhr("{{ url_for('visualization_data', interactions_filter = interactions_filter)}}")
  .header("Content-Type", "application/json")
  .post(
    JSON.stringify({
      "fileindicator": "{{fileindicator}}"
    }), function(error, rawData) {
      if (error) throw error;
      var json = JSON.parse(rawData.response);

      force
        .nodes(json.nodes)
        .links(json.links)
        .start();

      var link_scale = d3.scale.linear()
        .domain([0, d3.max(json.links, function(d) {
          return (d.value);
        })])
        .range([1, 13]);

      var link = g.selectAll(".link")
        .data(json.links)
        .enter().append("line")
        .attr("class", "link")
        .style("stroke-width", function(d) {
          return link_scale(d.value);
        })
        .style('stroke', link_color)
        .attr("fill-opacity", .75);


      var node = g.selectAll(".node")
        .data(json.nodes)
        .enter().append("g")
        .attr("class", "node")
        .call(force.drag)
        .style("fill", default_node_color);


      var radius_scale = d3.scale.sqrt()
        .domain([0, d3.max(json.nodes, function(d) {
          return (d.n_interactions);
        })])
        .range([2, 17]);

      if (isiOS) {
        // single click centers node
        var centerEvent = "click";
      } else {
        // double click centers node
        var centerEvent = "dblclick";
      }

      var all_links = d3.selectAll('.link');

      var all_nodes = d3.selectAll('.node');

      //populate select box
      var select_box = $('.chzn-select');
      select_box.empty();
      select_box.trigger('chosen:updated');
      var character_to_node_id = []
      for (var i = 0; i < all_nodes[0].length; i++) {
        var option = '<option value="' + all_nodes[0][i].__data__.index + '">' + all_nodes[0][i].__data__.name + '</option>';
        character_to_node_id.push(option);
        select_box.append("<option value='' selected='selected'></option>");
        select_box.append(character_to_node_id);


        var onClick = window.onClick = function(d, i) {
          // console.log(this)
          // console.log('d, i, this:', d, i, this);
          var index_of_clicked_node = d.index;

          // Moves clicked node to center
          var dcx = (w / 2 - d.x * zoom.scale());
          var dcy = (h / 2 - d.y * zoom.scale());

          zoom.translate([dcx, dcy]);
          g.transition()
            .duration(2000)
            .attr("transform", "translate(" + dcx + "," + dcy + ")scale(" + zoom.scale() + ")");

          //select all links NOT related to the clicked node and fade
          var fade_links = d3.selectAll('.link').filter(function(d) {
            return index_of_clicked_node !== d.source.index && index_of_clicked_node !== d.target.index;
          });
          // console.log(fade_links);
          fade_links.style('opacity', .2);

          var active_links = d3.selectAll('.link').filter(function(d) {
            return index_of_clicked_node === d.source.index || index_of_clicked_node === d.target.index;
          });
          // active_links.style('stroke', 'red')
          active_links.style('opacity', .85);

          var active_link_id_list = [];

          active_links[0].forEach(function(link) {
            active_link_id_list.push(link.__data__.target.index)
            active_link_id_list.push(link.__data__.source.index)
          });
          console.log('number of active links: ', active_link_id_list.length);
          //select all nodes not connected to the clicked node and fade
          var fade_nodes = d3.selectAll('.node').filter(function(d) {
            return !active_link_id_list.includes(d.index);
          });
          fade_nodes.style('opacity', .2);

          var active_nodes = d3.selectAll('.node').filter(function(d) {
            return active_link_id_list.includes(d.index);
          });

          console.log('number of active nodes: ', active_nodes);

          d3.selectAll('circle').filter(function(d, i) {
            if (d.name === name) {
              // call click event on the circle
              window.onClick(d, i);
            }
          });

          active_nodes.style('opacity', .85)
            .transition()
            .duration(1000)
            .style('fill', shining_node_color)
            .transition()
            .duration(1000)
            .style('fill', default_node_color);
        };

        node.append('circle')
          .attr("class", "circle")
          .attr("r", function(d, i) {
            return radius_scale(d.n_interactions);
          })
          .style('opacity', .85)
          .style('stroke', 'black')
          .style('stroke-width', 10)
          .style('stroke-opacity', 0.0)
          .call(force.drag)
          .on(centerEvent, onClick);

        var text_scale = d3.scale.linear()
          .domain([0, d3.max(json.nodes, function(d) {
            return (d.n_interactions);
          })])
          .range([6, 16]);


        node.append("text")
          .attr("dx", 12)
          .attr("dy", ".35em")
          .attr('fill', 'black')
          .text(function(d) {
            return d.name
          })
          .style("font-size", function(d) {
            return text_scale(d.n_interactions) + "px";
          })
          .style('font-family', "futura-pt")
          .style('fill', text_color);

        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("cx", function(d) {
              return d.x;
            })
            .attr("cy", function(d) {
              return d.y;
            });

          node.attr("transform", function(d) {
            return "translate(" + d.x + "," + d.y + ")";
          });
        });
        $('#loading-text').hide();

4

0 回答 0