Сделайте два экземпляра d3.forceCollide() хорошими игроками

Я хочу два случая d3.forceCollide(), В одном каждый узел отталкивается друг от друга, чтобы предотвратить перекрытие. Во втором только подмножество узлов отталкиваются друг от друга с гораздо большим радиусом.

Чтобы выполнить второе действие, я настраиваю метод initialize для фильтрации входящих узлов, например так:

function selective(force,filter){
    var init = force.initialize;
    force.initialize = function(_){return init(_.filter(filter));};
    return force;
}

var dpi = 90;  // approximate pixels per inch in SVG
var size = dpi * (1/4); // quarter-inch unit size

var universally_applied = 
    d3.forceCollide()
    .radius(size)
    .strength(1);

var selectively_applied =
        selective(
            d3.forceCollide(),
            function(d){return d.id === color;}
        )
        .radius(size*5)
        .strength(1);
}

Теперь это ПОЧТИ работает. Я создал скрипку, чтобы увидеть ее в действии: https://jsfiddle.net/jarrowwx/0dax43ue/38/ - каждый цветной круг должен отталкивать любой другой круг того же цвета на расстоянии. Любой другой цвет, он просто сталкивается и отталкивает его с пути.

Если я не изменю порядок, в котором определяются вещи, то избирательно приложенная сила применяется ТОЛЬКО к первому цвету (красному). Если я тасую data Массив, прежде чем применять силы, трудно точно определить, что происходит, но сила применяется к некоторым кругам, а не к большинству других, даже среди одного цвета.

Есть идеи, что здесь происходит, или как это исправить?

1 ответ

Решение

Команда D3 решила, что это поведение было ошибкой ( Изоляция сил для подмножества узлов? # 72), и исправила ее. Исправление было включено в версию 1.0.4 d3-force, которая доступна как часть полной сборки D3 начиная с версии 4.4.0.

Проблема решается с помощью решения, предложенного "Частичные силы на узлах в D3.js", и код работает так, как задумано сейчас.

Другие вопросы по тегам