Open xiaoiver opened 1 year ago
d3.force 提供了 tick 方法,配合 stop 可以完成同步方式下的 static force layout: https://github.com/d3/d3-force#simulation_tick
tick
stop
const simulation = d3.forceSimulation(nodes) // 省略其他参数 .stop(); for () { simulation.tick(); } // 一次性计算完成后渲染
文档中也建议这种方式适合放在 WebWorker 中运行,同时也不会触发 tick 事件,同步计算完成后进行渲染等操作。
如果把 Worker 中的首次布局计算看作服务端渲染,整个过程有点像 React SSR 中的 hydrate:
配合 Supervisor 使用时,不关心 tick,只关心全部迭代完成后的最终结果:
const graph = new Graph(); const force = new D3ForceLayout(); const supervisor = new Supervisor(graph, force, { iterations: 1000 }); supervisor.on('layoutend', (positions) => { // 进行首次渲染,并绑定节点拖拽事件 createNodesEdges(positions); // 更新图模型中的数据 graph.mergeNodeData(); }); supervisor.start();
当对单个节点进行拖拽交互时:
function moveAt(target, canvasX, canvasY) { // 更新图模型当前节点的数据 graph.mergeNodeData(positions.nodes[i].id, { x: canvasX - shiftX, y: canvasY - shiftY, }); // 停止当前布局 force.stop(); // 开始新的布局计算 force.assign(graph, { center: [200, 200], // The center of the graph by default preventOverlap: true, nodeSize: 20, onTick: (positions) => { updateNodesEdges(positions); }, }); }
在 Worker 中执行 static layout:
const graph = new Graph(); const layout = new D3ForceLayout(); layout.stop(); layout.tick(1000); // 通知主进程计算完成
之前在 layout 中的使用方式:https://github.com/antvis/layout/blob/master/src/layout/force/force.ts#L232-L248
使用文档 & 例子: https://observablehq.com/d/2db6b0cc5e97d8d6#cell-1315
触发 tick 更好一些,在渲染性能不是瓶颈的情况下,对于耗时较长的大图,使用tick呈现布局的变化过程可以给用户更好的体验。当然可能不同业务场景会不一样,但作为库应当提供这个接口。
d3.force 提供了
tick
方法,配合stop
可以完成同步方式下的 static force layout: https://github.com/d3/d3-force#simulation_tick文档中也建议这种方式适合放在 WebWorker 中运行,同时也不会触发
tick
事件,同步计算完成后进行渲染等操作。如果把 Worker 中的首次布局计算看作服务端渲染,整个过程有点像 React SSR 中的 hydrate:
在 Supervisor 中使用
配合 Supervisor 使用时,不关心
tick
,只关心全部迭代完成后的最终结果:当对单个节点进行拖拽交互时:
在 Worker 中执行 static layout:
之前在 layout 中的使用方式:https://github.com/antvis/layout/blob/master/src/layout/force/force.ts#L232-L248