Tengo nodos en un diseño dirigido a la fuerza D3 que están configurados en. fijo = verdadero. Si establezco los valores .xo .y, los nodos en sí no se mueven a su nueva posición.

Esta es mi función:

function fixNode(idArray, locationX, locationY) {
    for ( x = 0; x < idArray.length; x++ ) {
        for ( y = 0; y < nodes.length; y++ ) {
            if (nodes[y].id == idArray[x]) {
                nodes[y].fixed = true;
                nodes[y].x = 50;
                nodes[y].y = 50;
                break;
            }
        }
    }
}

ACTUALIZACIÓN 1:

Aquí está la función de trabajo basada en el consejo de Jason:

function fixNode(idArray, locationX, locationY) {
    for ( x = 0; x < idArray.length; x++ ) {
        for ( y = 0; y < nodes.length; y++ ) {
            if (nodes[y].id == idArray[x]) {
                nodes[y].fixed = true;
                nodes[y].x = 50;
                nodes[y].y = 50;
                nodes[y].px = 50;
                nodes[y].py = 50;
                break;
            }
        }
    }
    tick();
}
8
Elijah 8 may. 2012 a las 20:49

1 respuesta

La mejor respuesta

El diseño dirigido por la fuerza está desacoplado del renderizado real. Normalmente tiene un manejador de ticks, que actualiza los atributos de sus elementos SVG para cada "tick" del algoritmo de diseño (lo bueno del desacoplamiento es que, en su lugar, representa a un <canvas>, o algo más).

Entonces, para responder a su pregunta, simplemente debe llamar a este controlador directamente para actualizar los atributos de sus elementos SVG. Por ejemplo, su código podría verse así:

var node = …; // append circle elements

var force = d3.layout.force()
    .nodes(…)
    .links(…)
    .on("tick", tick)
    .start();

function tick() {
  // Update positions of circle elements.
  node.attr("cx", function(d) { return d.x; })
      .attr("cy", function(d) { return d.y; });
}

Entonces, simplemente podría llamar a tick() en cualquier momento y actualizar las posiciones de los elementos.

Puede tener la tentación de llamar a force.tick(), pero esto está destinado a ser utilizado como una alternativa sincrónica a force.start(): puede llamarlo repetidamente y cada llamada ejecuta un paso del algoritmo de diseño. Sin embargo, hay una variable alpha interna que se usa para controlar el recocido simulado utilizado internamente, y una vez que el diseño se haya "enfriado", esta variable será 0 y las llamadas posteriores a force.tick() no tendrán ningún efecto. (Es cierto que sería bueno si force.tick() siempre disparara un evento tick independientemente del enfriamiento, pero ese no es el comportamiento actual).

Como anotó correctamente en los comentarios, si configura manualmente d.x y d.y, también debe configurar d.px y d.py con los mismos valores si desea que el nodo permanezca en cierta posición.

14
Jason Davies 28 sep. 2012 a las 23:11
Gracias, ahora lo entiendo. Acabo de probar el comportamiento y quería señalar algo que puede confundir a las personas que provienen de los ejemplos predeterminados: debe cambiar los valores px / py así como los valores x / y si el nodo se ha estado moviendo. Publicaré la función actualizada arriba.
 – 
Elijah
9 may. 2012 a las 06:32
Si el nodo tiene enlaces de conexión, se retira. Me pregunto cómo se puede eludir eso ...
 – 
Qasim
13 dic. 2019 a las 11:10