2015-09-01 3 views
3

Рассмотрим любое усилие направленное d3 анимации, такие как:d3 сила-направленного макет расширяет повторного нагрева

http://bl.ocks.org/mbostock/1062288

нагрузки, что граф и пусть узлы располагаются так, чтобы они не двигаются. Наведите указатель мыши на оранжевый узел и отпустите мышь. Нажмите и ничего не делайте. Вы увидите, что все узлы немного перемещаются внутрь, а затем расширяются до нормального уровня.

Мне не нравится это ненужное движение, и мне нужно его удалить.

Я считаю, что это связано с тем, что график «разогрет» (см. https://github.com/mbostock/d3/wiki/Force-Layout ), который устанавливает альфа-параметр в 0,1. В частности, я вижу, что ненужное движение происходит сразу после любого из следующего.

  1. новый узел добавляется к графу
  2. узел удаляется из графа
  3. force.drag() называется.

Что именно вызывает это «ненужное движение» и как его можно отключить? (Без отключения узла увлекая)

+0

возможно дубликат [d3.js статической компоновки силы] (http://stackoverflow.com/questions/31021663/d3-js -static-force-layout) – kwoxer

+0

Разметка силы выполняется именно для этих пересчетов позиций узлов. Вы можете установить узлы в определенную позицию, если вы действительно этого хотите. Или, возможно, через 3 секунды вы установите фиксированные узлы. Это зависит от того, что вы хотите иметь в конце. – kwoxer

+0

@kwoxer Это не дубликат другого вопроса. Этот вопрос * не * о том, как ведут себя узлы, когда график инициализируется. Я отредактировал мой вопрос, чтобы сделать его более понятным. – mareoraft

ответ

0

Обычно, когда force.resume() уволен, значение альфа перескакивает от 0 до 0,1. Ослабляя альфа вверх, мы можем скрыть «ненужное движение».

Я по-прежнему открыт для других идей и решений.

старая функция:

force.resume = function() { 
    return force.alpha(.1); 
}; 

замена функции:

force.resume = function() { 
    var alpha = force.alpha() 
    if(alpha < 0.005){ alpha = 0.0055 } 
    else if(alpha < 0.11){ alpha += 0.0006 } 
    return force.alpha(alpha); 
}; 
0

в

// Toggle children on click. 
function click(d) { 
    if (!d3.event.defaultPrevented) { 
    if (d.children) { 
     d._children = d.children; 
     d.children = null; 
    } else { 
     d.children = d._children; 
     d._children = null; 
    } 
    update(); 
    } 
} 

Вы можете переместить обновления для детей открыть только

// Toggle children on click. 
function click(d) { 
    if (!d3.event.defaultPrevented) { 
    if (d.children) { 
     d._children = d.children; 
     d.children = null; 
     update(); 
    } else { 
     d.children = d._children; 
     d._children = null; 
    } 

    } 
} 

поэтому узел без детей (оранжевый) не будет обновляться по щелчку.

+0

Я не думаю, что это отвечает на вопрос. Вопрос не специфичен для деревьев. – mareoraft

+0

Он/она хотел избавиться от обновления, когда щелкнули оранжевые круги. Он делает это только при замене двух строк кода. Насколько проще это может быть? Хотя проголосовавший ответ ncie и завершен, он предлагает сделать много изменений в основной библиотеке, и я не думаю, что это то, что OP хочет сделать! – MrE

+0

Я OP, и я в порядке с редактированием библиотеки, если она решает проблему. Я не хотел избавляться от обновления, но я хотел предотвратить ненужное возмущение или спазм, которые создают узлы, когда график изменяется из неподвижного положения в движущуюся позицию (что происходит, когда график все еще, а затем вы перетаскиваете узел в этой [скрипке] (https://jsfiddle.net/Lr833scv/)). Если вы уверены, что ваш ответ делает это, пожалуйста, переделайте скрипку и верните ссылку на свое решение здесь. – mareoraft

3

Поведение происходит в основном от альфы. Альфа функция в d3:

force.alpha = function(x) { 
    if (!arguments.length) return alpha; 
    x = +x; 
    if (alpha) { 
    if (x > 0) alpha = x; else alpha = 0; 
    } else if (x > 0) { 
    event.start({ 
     type: "start", 
     alpha: alpha = x 
    }); 
    d3.timer(force.tick); 
    } 
    return force; 
}; 

Так что, когда альфа называется, он запускает событие клеща, если он больше, чем 0

В случае клеща, в самом начале, вы можете увидеть отрезанное что в результате чего 'заморозить' вы упомянули:

if ((alpha *= .99) < .0005) { 
     event.end({ 
      type: "end", 
      alpha: alpha = 0 
     }); 
     return true; 
     } 

Теперь, если мы посмотрим на dragmove, она вызывает функцию резюме:

function dragmove(d) { 
     d.px = d3.event.x, d.py = d3.event.y; 
     force.resume(); 
    } 

, который вызывает функцию альфа со значением 0,1:

force.resume = function() { 
     return force.alpha(.1); 
    }; 

Чтобы остановить прыжок, а также замораживание на 0,0005, я не вижу себя какой-либо публичную функцию, вы можете использовать.

У меня есть пример fiddle, который удалил код из функции tick, которая вызывает замораживание, а также изменила функцию возобновления, чтобы начать с меньшей альфы.

Я считаю, что это дает результат, который вы ищете, но, конечно же, я бы не советовал настраивать библиотеку.

Возможно, кто-то знает, как переопределить функцию тика без изменения источника.

+0

Думаю, мне придется настроить библиотеку. Я посмотрю, смогу ли я понять, что такое «event.start» и как оно относится к «force.start». – mareoraft

+0

У меня возникли проблемы с тем, чтобы пройти через строку 'var кандидаты = соседи [i], j = -1, l = candidates.length, x;' в библиотеке. Он использует 'i' вне функции. Кроме того, если входные позиции не указаны, дает ли случайное число? – mareoraft

+0

Эта функция вызывается только в том случае, если значения x и y не являются числами, из этой функции в методе start: 'for (i = 0; i