Событие клика для нескольких складных деревьев d3 на одной странице

0

Я реализую несколько разворачиваемых деревьев на странице, используя http://bl.ocks.org/mbostock/4339083

Но я столкнулся с проблемой события click. Когда я нажимаю узел, он не сворачивается и не расширяется. Складываемое событие работает только для последнего дерева (Дерево проблем), поскольку оно загружено последним svg. (Пример: http://tinypic.com/r/2zzqcn5/8)

Как заставить событие click работать для всего дерева? Будет ли использование iframe для каждого графика решить эту проблему? если да, то как это сделать?

Благодарю.

Данные JSON для каждого вызова функции collapse_graph (type):

1-я итерация: type = Артефакты

{"name":"artifacts","children":[
    {"name":"weights","children":[]},
    {"name":"sampling compartment","children":[]},
    {"name":"depth guage","children":[
       {"name":"Decomp8","children":[
          {"name":"Pressure gauge","children":[]}]},
          {"name":"Decomp9","children":[
              {"name":"a sensor that determines the depth","children":[]}
       ]}
    ]}
]}

Вторая итерация: type = Behavior

{"name":"behaviors","children":[
    {"name":"Hydrostatic pressure","children":[
        {"name":"Decomp6","children":[
            {"name":"Ro","children":[]},
            {"name":"h","children":[]},
            {"name":"g","children":[]}
        ]}
    ]}
]}

Третья итерация: type = Issue

{"name":"issues","children":[
    {"name":"withstanding pressure in depth","children":[]}
]}

Код:

/* Collapsible Tree Global variables */
var tree, diagonal, svg;
var inc = 0, duration = 750, root;


$('#tabs').append("<h2>Artifacts</h2>");
collapse_graph('artifact');            
$('#tabs').append("<h2>Behaviors</h2>");            
collapse_graph('behavior');            
$('#tabs').append("<h2>Issues</h2>");          
collapse_graph('issue');


function collapse(d) {
    if (d.children) {
        d._children = d.children;
    d._children.forEach(collapse);
    d.children = null;
    }
}

function collapse_graph(type){

var data = {};
    //data['name'] = type + "s";
    //data['children'] = getChildrenEntities(type);

    if(type == 'artifact') {
    data = JSON.parse('{"name":"artifacts","children":[{"name":"weights","children":[]},{"name":"sampling compartment","children":[]},{"name":"depth guage","children":[{"name":"Decomp8","children":[{"name":"Pressure gauge","children":[]}]},{"name":"Decomp9","children":[{"name":"a sensor that determines the depth","children":[]}]}]}]}');
    }

    if (type == 'behavior') {
    data = JSON.parse('{"name":"behaviors","children":[{"name":"Hydrostatic pressure","children":[{"name":"Decomp6","children":[{"name":"Ro","children":[]},{"name":"h","children":[]},{"name":"g","children":[]}]}]}]}');
    }

    if (type == 'issue') {
    data = JSON.parse('{"name":"issues","children":[{"name":"withstanding pressure in depth","children":[]}]}');
    }

    // d3 business.
    var width = 800;
    var height = 500;

tree = d3.layout.tree().size([height, width]);

diagonal = d3.svg.diagonal().projection(function(d) { return [d.y, d.x]; });

svg = d3.select("#tabs").append("svg")
    .attr("width", width)
    .attr("height", height)
.append("g")
    .attr("transform", "translate(100,0)");

  root = data;
  root.x0 = height / 2;
  root.y0 = 0;

  root.children.forEach(collapse);
  update(root);

d3.select(self.frameElement).style("height", "800px");
}

function update(source) {

  // Compute the new tree layout.
  var nodes = tree.nodes(root).reverse(),
  links = tree.links(nodes);

  // Normalize for fixed-depth.
  nodes.forEach(function(d) { d.y = d.depth * 180; });

  // Update the nodes…
  var node = svg.selectAll("g.node")
  .data(nodes, function(d) { return d.id || (d.id = ++inc); });

  // Enter any new nodes at the parent previous position.
  var nodeEnter = node.enter().append("g")
  .attr("class", "node")
  .attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 +       ")"; })
  .on("click", click);

  nodeEnter.append("circle")
  .attr("r", 1e-6)
  .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });

  nodeEnter.append("text")
  .attr("x", function(d) { return d.children || d._children ? -10 : 10; })
  .attr("dy", ".35em")
  .attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; })
  .text(function(d) { return d.name; })
  .style("fill-opacity", 1e-6);

  // Transition nodes to their new position.
  var nodeUpdate = node.transition()
  .duration(duration)
  .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });

  nodeUpdate.select("circle")
  .attr("r", 4.5)
  .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });

  nodeUpdate.select("text")
  .style("fill-opacity", 1);

  // Transition exiting nodes to the parent new position.
  var nodeExit = node.exit().transition()
  .duration(duration)
  .attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; })
  .remove();

  nodeExit.select("circle")
  .attr("r", 1e-6);

  nodeExit.select("text")
  .style("fill-opacity", 1e-6);

  // Update the links…
  var link = svg.selectAll("path.link")
  .data(links, function(d) { return d.target.id; });

  // Enter any new links at the parent previous position.
  link.enter().insert("path", "g")
  .attr("class", "link")
  .attr("d", function(d) {
    var o = {x: source.x0, y: source.y0};
    return diagonal({source: o, target: o});
  });

  // Transition links to their new position.
  link.transition()
  .duration(duration)
  .attr("d", diagonal);

  // Transition exiting nodes to the parent new position.
  link.exit().transition()
  .duration(duration)
  .attr("d", function(d) {
    var o = {x: source.x, y: source.y};
    return diagonal({source: o, target: o});
  })
  .remove();

  // Stash the old positions for transition.
  nodes.forEach(function(d) {
  d.x0 = d.x;
  d.y0 = d.y;
  });
  inc = 0;
}

// Toggle children on click.
function click(d) {
  if (d.children) {
    d._children = d.children;
    d.children = null;
  } 
  else {
    d.children = d._children;
    d._children = null;
  }

  update(d);
}
  • 0
    Подключены ли узлы во всех трех деревьях к одному и тому же слушателю (т.е. функция click )?
  • 0
    Привет, @FernOfTheAndes !! Да. Вызывается одна и та же функция для создания всего графа.
Показать ещё 11 комментариев
Теги:
d3.js
tree

1 ответ

2

Решение хранит данные, svg в массиве и в событии click вызывает функцию с соответствующими данными дерева.

Вот рабочий код:

/* Collapsible Tree Global variables */
var tree, diagonal, svg = [];
var inc = 0, duration = 750, root = [];


$('#tabs').append("<h2>Artifacts</h2>");
collapse_graph('artifact');            
$('#tabs').append("<h2>Behaviors</h2>");            
collapse_graph('behavior');            
$('#tabs').append("<h2>Issues</h2>");          
collapse_graph('issue');

function collapse_graph(type){

var data = {};
//data['name'] = type + "s";
//data['children'] = getChildrenEntities(type);

if(type == 'artifact') {
data = JSON.parse('{"name":"artifacts","children":[{"name":"weights","children":[]},{"name":"sampling compartment","children":[]},{"name":"depth guage","children":[{"name":"Decomp8","children":[{"name":"Pressure gauge","children":[]}]},{"name":"Decomp9","children":[{"name":"a sensor that determines the depth","children":[]}]}]}]}');
}

if (type == 'behavior') {
data = JSON.parse('{"name":"behaviors","children":[{"name":"Hydrostatic pressure","children":[{"name":"Decomp6","children":[{"name":"Ro","children":[]},{"name":"h","children":[]},{"name":"g","children":[]}]}]}]}');
}

if (type == 'issue') {
data = JSON.parse('{"name":"issues","children":[{"name":"withstanding pressure in depth","children":[]}]}');
}

// d3 business.
var width = 800;
var height = 500;

tree = d3.layout.tree().size([height, width]);

diagonal = d3.svg.diagonal().projection(function(d) { return [d.y, d.x]; });

svg[type] = d3.select("#tabs").append("svg")
    .attr("type", type)
    .attr("width", width)
    .attr("height", height)
    .append("g")
    .attr("transform", "translate(100,0)");

root[type] = data;
  root[type].x0 = height / 2;
  root[type].y0 = 0;

  //root.children.forEach(collapse);
  update(root[type], type);

  //d3.select(self.frameElement).style("height", "800px");
}

function update(source,type) {

  // Compute the new tree layout.
  var nodes = tree.nodes(root[type]).reverse(),
  links = tree.links(nodes);

  // Normalize for fixed-depth.
  nodes.forEach(function(d) { d.y = d.depth * 180; });

  // Update the nodes…
  var node = svg[type].selectAll("g.node")
  .data(nodes, function(d) { return d.id || (d.id = ++inc); });

  // Enter any new nodes at the parent previous position.
  var nodeEnter = node.enter().append("g")
  .attr("class", "node")
  .attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 +")"; }).on('click', click);

  nodeEnter.append("circle")
  .attr("r", 1e-6)
  .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });

  nodeEnter.append("text")
  .attr("x", function(d) { return d.children || d._children ? -10 : 10; })
  .attr("dy", ".35em")
  .attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; })
  .text(function(d) { return d.name; })
  .style("fill-opacity", 1e-6);

  // Transition nodes to their new position.
  var nodeUpdate = node.transition()
  .duration(duration)
  .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });

  nodeUpdate.select("circle")
  .attr("r", 4.5)
  .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });

  nodeUpdate.select("text")
  .style("fill-opacity", 1);

  // Transition exiting nodes to the parent new position.
  var nodeExit = node.exit().transition()
  .duration(duration)
  .attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; })
  .remove();

  nodeExit.select("circle")
  .attr("r", 1e-6);

  nodeExit.select("text")
  .style("fill-opacity", 1e-6);

  // Update the links…
  var link = svg[type].selectAll("path.link")
  .data(links, function(d) { return d.target.id; });

  // Enter any new links at the parent previous position.
  link.enter().insert("path", "g")
  .attr("class", "link")
  .attr("d", function(d) {
    var o = {x: source.x0, y: source.y0};
    return diagonal({source: o, target: o});
  });

  // Transition links to their new position.
  link.transition()
  .duration(duration)
  .attr("d", diagonal);

  // Transition exiting nodes to the parent new position.
  link.exit().transition()
  .duration(duration)
  .attr("d", function(d) {
    var o = {x: source.x, y: source.y};
    return diagonal({source: o, target: o});
  })
  .remove();

  // Stash the old positions for transition.
  nodes.forEach(function(d) {
    d.x0 = d.x;
    d.y0 = d.y;
  });
  inc = 0;
}

// Toggle children on click.
function click(d) {
  if (d.children) {
    d._children = d.children;
    d.children = null;
  } 
  else {
    d.children = d._children;
    d._children = null;
  }
  var type = $(this).parents('svg').attr('type');
  update(d, type);
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню