#javascript #cytoscape.js
#javascript #cytoscape.js
Вопрос:
Если я клонирую конфигурацию макета с Object.assign
помощью и пытаюсь использовать этот макет, cytoscape быстро вызывает ошибку нехватки памяти. Я могу обойти это, просто определив второй макет, в основном идентичный первому, и не клонируя, но мне интересно узнать причину проблемы или возможную ошибку в cytoscape.
В этом примере кода щелкните add and layout 2
сразу после загрузки страницы, и она зависнет / закончится память. (Имейте под рукой диспетчер задач, чтобы отключить вашу вкладку или браузер.) Различные комбинации добавления узлов и запуска клонированного макета в основном будут зависать, но не всегда.
let cy
const layout1 = {
name: 'euler',
springLength: edge => 80,
mass: node => 4,
randomize: true,
animate: false,
gravity: -1.2,
maxIterations: 1000,
maxSimulationTime: 4000,
}
const layout2 = Object.assign({}, layout1, {
fit: false,
animate: true,
randomize: false,
})
document.addEventListener('DOMContentLoaded', function() {
cy = cytoscape({
container: document.getElementById('cy'),
layout: layout1,
style: [
{
selector: 'node',
style: {
label: 'data(id)',
},
},
],
elements: [
{ data: { id: 'a' } },
{ data: { id: 'b' } },
{ data: { id: 'a_b', source: 'a', target: 'b' } },
],
})
})
function add() {
cy.add([
{ data: { id: 'c' } },
{ data: { id: 'd' } },
{ data: { id: 'c_d', source: 'c', target: 'd' } },
])
// cy.layout(layout2).run()
}
function doLayout1() {
cy.layout(layout1).run()
}
function doLayout2() {
cy.layout(layout2).run()
}
function addAndLayout2() {
add()
doLayout2()
}
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.5.0/cytoscape.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/cytoscape-euler@1.2.1/cytoscape-euler.min.js"></script>
</head>
<style>
body {
height: 100%;
}
#cy {
height: 100%;
flex-grow: 1;
}
.main {
height: 100vh;
display: flex;
flex: 1;
}
</style>
<body>
<button onclick="add()">add nodes</button>
<button onclick="doLayout1()">layout 1</button>
<button onclick="doLayout2()">layout 2</button>
<button onclick="addAndLayout2()">add and layout 2</button>
<div class="main">
<div id="cy"></div>
</div>
</body>
</html>
Ответ №1:
Это не имеет никакого отношения к Ojbect.assign
(даже если вы неправильно скопировали объект, он не должен зависать).
Причина в randomize
опции. Для этого конкретного графика, когда для параметра randomize установлено значение false
, макет никогда не заканчивается. Просто удалите randomize: false
из второго макета или после добавления новых узлов и перед запуском layout2
запустите random
макет (или просто рандомизируйте узлы вручную) — layout2
завершится.
Проблема в том, что: макет должен завершиться в какой-то момент (в худшем случае, когда достигается максимальное количество итераций). Но этот конкретный макет никогда не завершается.
Интересно то, что этот простой график оказывается одним из худших случаев и для некоторых других алгоритмов компоновки (for randomized: false
). Я пытался cose-bilkent
. Это также занимает немного больше времени и завершается при достижении максимального количества итераций (установка numIter
параметра на меньшее число приведет к досрочному завершению, ухудшению качества) — но результат действительно плохой.
Комментарии:
1. Спасибо, что разъяснили, что я ввел ложную ассоциацию в
Object.assign
, это очень помогает! Интересно,randomized
требуется ли это, или узлы точно перекрываются, поэтому это приводит к сбою физического моделирования? Я попробую проверить эту теорию, но мне было интересно, о чем вы думаете.2. Что вы подразумеваете под »
randomized
требуется»? Если бы это было необходимоtrue
, то это не было бы вариантом. Когда применяется рандомизированныйfalse
пошаговый макет — текущие позиции узлов используются в качестве начальной позиции в алгоритме компоновки. Это хорошо для сохранения ментальной карты пользователя. Когда это верно, изначально узлам назначаются случайные точки, а затем выполняется алгоритм компоновки. Это не обязательно перекрытие, это общее состояние позиций узлов (даже если вы просто добавляете узелc
в add function , он никогда не завершается).3. В любом случае макет должен завершиться. Либо когда он сходится, либо достигается максимальное количество итераций. Возможно, вы можете сообщить об этом как о проблеме.
4. Я имею в виду, что с
randomize: false
макетом происходит сбой, поэтому, похоже, это неявно требуетсяtrue
. Я понимаю, что макет должен каким-то образом урегулировать / завершить, но в данном случае это явно не так.