多次迭代的布局在 Worker 中运行是否还需要触发 tick 事件?
- Dominant language
- TypeScript
- Stars
- 276
- Forks
- 60
- PR merge metrics
- No merged PRs in 30d
Description
d3.force 提供了 `tick` 方法,配合 `stop` 可以完成同步方式下的 [static force layout](https://bl.ocks.org/mbostock/1667139):
https://github.com/d3/d3-force#simulation_tick
```js
const simulation = d3.forceSimulation(nodes)
// 省略其他参数
.stop();
for () {
simulation.tick();
}
// 一次性计算完成后渲染
```
文档中也建议这种方式适合放在 WebWorker 中运行,同时也不会触发 `tick` 事件,同步计算完成后进行渲染等操作。
如果把 Worker 中的首次布局计算看作服务端渲染,整个过程有点像 React SSR 中的 [hydrate](https://beta.reactjs.org/reference/react-dom/hydrate#hydrating-server-rendered-html):
* Worker 中执行 static force layout,返回结果给主线程。类似返回服务端渲染结果 HTML 片段
* 主线程接收到首次布局结果,需要更新图模型中的数据(如果后续需要调用 assign 的话),便于 drag 时继续执行使用。类似给 HTML 添加交互
## 在 Supervisor 中使用
配合 Supervisor 使用时,不关心 `tick`,只关心全部迭代完成后的最终结果:
```js
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();
```
当对单个节点进行拖拽交互时:
```js
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:
```js
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
Contributor guide
Assessment
This issue has not been assessed yet.