Динамическое добавление узлов в Cytoscape - PullRequest
4 голосов
/ 01 октября 2019

Моя компания создает редактор графического представления для чат-ботов. Для этого мы используем Cytoscape вместе с расширением cytoscape-cola. Одна из проблем, с которой мы сталкиваемся, - это динамическое добавление новых узлов в граф без их перекрытия с существующими узлами на графике.

Я просматривал предыдущие подобные вопросы (перечисленные ниже), но безрезультатно:

Cytoscape - обрабатывать заблокированные узлы

Я попробовал решение там, то есть применение макета только к вновь добавленным узлам, но они продолжают располагаться в центре экрана.

Cytoscape -игнорировать заблокированные узлы

Я пробовал решение, упомянутое здесь, но независимо от блокировки узлов за один раз, т.е. cy.nodes().lock() или по отдельности, т.е. cy.nodes().forEach(node => node.lock()), заблокированные узлы все еще продолжают двигаться. Здесь также интересно отметить, что при индивидуальной блокировке узлов вновь добавленные узлы также блокируются независимо от того, блокирую ли я вызов выше или нет.

Cytoscape - динамически добавлять узлы безПеремещение других

Я также попробовал это решение, но заблокированные узлы все еще перемещаются, и полный макет изменяется - иногда совсем, иногда просто немного.

Код

Этов настоящее время то, что я использую для построения графа:

const layoutConfig = {
    name: "cola",
    handleDisconnected: true,
    animate: true,
    avoidOverlap: true,
    infinite: false,
    unconstrIter: 1,
    userConstIter: 0,
    allConstIter: 1,
    ready: e => {
        e.cy.fit()
        e.cy.center()
    }
}
this.graph = Cytoscape({ ... })

this.layout = this.grapg.makeLayout(layoutConfig)

this.layout.run();

Это то, что я использую для добавления новых узлов к графу:

const addElements = (elements: ElementSingular | ElementMultiple) => {
    this.graph.nodes().forEach(node => {
        node.lock();
    })

    this.graph.add(elements)

    this.layout = this.graph.makeLayout(layoutConfig)

    this.layout.on("layoutready", () => {
        this.nodes().forEach(node => {
            node.unlock();
        })
    })

    this.layout.run()

    this.graph.nodes().forEach(node => {
        node.unlock();
    })
}

Я бы хотелвыполните одно из следующих действий:

  1. Поймите, что я делаю неправильно , если то, что я пытаюсь выполнить, возможно, но мой код не достигает этого
  2. Поймите, почему я не смогу это сделать, то есть ограничения, которые управляют этим

1 Ответ

1 голос
/ 02 октября 2019

Редактировать: Это то, что вы искали? https://output.jsbin.com/hokineluwo

Редактировать: я раньше не видел, но вы также unlocking узлы сразу после вызова макета, Cola асинхронный, запуск только запускает процесс. Удалите этот код и используйте только метод layoutstop.

Я не помню правильно, но я думаю, что кола продолжает перемещать элементы после layoutready. С их код :

// trigger layoutready when each node has had its position set at least once

Существует событие layoutstop, которое вы можете использовать (и cytoscape-cola тоже использует ).

Из документов (выделено мое):

layoutready: когда макет установил начальные позиции для всех узлов (, но, возможно, не конечные позиции )

layoutstop: когда макет завершился полностью или иным образом прекратил работу

Я попытался бы удалить этот обратный вызов и проверить, дает ли он хорошие результаты. Кроме того, вы должны попытаться воспроизвести его здесь: http://jsbin.com/fiqugiq

Это позволяет другим (даже авторам) поиграть с ним и посмотреть, нашли ли вы ошибку или нет.

...