Pregunta

Mi comprensión de D3 es actualmente bastante limitado y actualmente estoy jugando con un ejemplo de dendrograma de D3.js. Se puede encontrar en varios lugares: en esta versión interactiva por ejemplo.

Cuando lo implemento, todo va bien hasta que intente actualizar una propiedad como el diámetro del círculo de los nodos. Si lo hago (usando un marco interactivo como Angularjs que observa el cambio de parámetros): los nodos cambian de tamaño. Así que no hay problema todavía. Sin embargo, si hago clic en uno de los nodos, el tamaño se restablece al tamaño de inicialización en lugar del nuevo.

Cuando se hace clic en un nodo, siga la función click:

 var nodeEnter = node.enter().append("g")
                        .attr("class", "dendrogramnode2")
                        .on("click", click);

La función de clic llama una función de actualización.

        function click(d) {
            if (d.children) {
                d._children = d.children;
                d.children = null;
            } else {
                d.children = d._children;
                d._children = null;
            }
            update(d);
        }

que luego actualiza el dendrograma y abre o cierra los nodos necesarios.

function update(source) {

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

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

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

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

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

  nodeEnter.append("text")
      .attr("x", 10)
      .attr("dy", ".35em")
      .attr("text-anchor", "start")
      //.attr("transform", function(d) { return d.x < 180 ? "translate(0)" : "rotate(180)translate(-" + (d.name.length * 8.5)  + ")"; })
      .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 "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; })

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

  nodeUpdate.select("text")
      .style("fill-opacity", 1)
      .attr("transform", function(d) { return d.x < 180 ? "translate(0)" : "rotate(180)translate(-" + (d.name.length + 50)  + ")"; });

  // TODO: appropriate transform
  var nodeExit = node.exit().transition()
      .duration(duration)
      //.attr("transform", function(d) { return "diagonal(" + 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's 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's 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;
  });
}

Esta función de actualización se llama así:

  1. en la inicialización -> No hay problema (ejemplo: círculo r= 5)

  2. Cuando se actualiza un parámetro -> No hay problema, las actualizaciones de los parámetros. (Ejemplo: Círculo R= 10)

  3. Cuando hace clic en un nodo -> problemático -> El gráfico toma los parámetros iniciales. (Ejemplo: círculo r= 5)

  4. Todo esto probablemente tiene mucho que ver con el alcance y cómo JavaScript maneja la categoría de datos, pero no sé cómo hacerlo correctamente. O bien necesito poder acceder a las nuevas propiedades en lugar de las antiguas.

    ¿Hay alguna manera de

    1. ¿Adaptar el código para que se tome el nuevo parámetro en lugar de los antiguos?

    2. Enlace los parámetros al grupo SVG como objeto (probablemente no tan eficiente), así que ¿Puede alcanzarlo manualmente desde cualquier alcance utilizando los selectores D3?

¿Fue útil?

Solución

He establecido una propiedad en el elemento DOM para aquellos atributos que no difieren por datum.

            function dograph(p){
                //paramater object is passed and it's name is "p"
                d3.select(elementid).selectAll("svg")[0][0]["p"] = p
                //at some point update function gets called as part of an event and p is no longer available. 

                //someSvgElement
                        .on("mouseover"){update())}

                function update(source) {
                    var p = d3.select(elementid).selectAll("svg")[0][0]["p"];
                    //stuff happens
                }
            }

podría no ser la solución perfecta, pero funciona para mí.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top