【发布时间】:2017-01-19 21:32:01
【问题描述】:
好了,别笑了。我正在尝试制作弯曲的边缘,绕过源和目标之间的节点。我不知道怎么做(我读了http://js.cytoscape.org/#style/bezier-edges,但没看懂),所以我把假节点放在从源到目标的路上空的地方,并做了一系列的边缘。结果很可笑:
这样做的正确方法是什么?我的目标是稍微优雅一点,比如:
来自http://twitter.github.io/labella.js/
根据下面@maxkfranz 的建议,我确实更接近了:
但最终还是决定放弃。时间太长了回到直边。如果有人读过这篇文章并且可以描述一种在 Cytoscape.js 或其他工具中实现我的目标的方法,我很想听听。
为了在放弃之前明确自己在做什么,我:
- 在网格上布置节点,以便在它们之间总是有一个空的网格单元 同一行上的任何两个节点(这不太理想,因为空 单元格应尽可能窄)
- 对于源节点和目标节点之间的网格布局上的每一行:
- 指定最接近源(或 前一个航路点)到通过空网格单元的目标,
- 将路点的行/列坐标转换为像素坐标,
- 将它们转换为距离/重量值(基于描述的功能 here)
- 将这些用于未捆绑的贝塞尔控制点。
这是我的代码中最相关的部分:
function waypoints(from, to) {
let stubPoint = { row: from.data().row, col: from.data().col,
distance: 0, weight: .5, };
if (from.data().layer === to.data().layer)
return [stubPoint];
let fromCol = from.data().col,
curCol = fromCol,
toCol = to.data().col,
fromRow = from.data().row,
curRow = fromRow,
toRow = to.data().row,
fromX = from.position().x,
fromY = from.position().y,
toX = to.position().x,
toY = to.position().y,
x = d3.scaleLinear().domain([fromCol,toCol]).range([fromX,toX]),
y = d3.scaleLinear().domain([fromRow,toRow]).range([fromY,toY]);
let rowsBetween = _.range(fromRow, toRow).slice(1);
let edgeLength = pointToPointDist(x(fromCol),y(fromRow),x(toCol),y(toRow));
let points = rowsBetween.map(
(nextRow,i) => {
let colsRemaining = toCol - curCol;
let colsNow = Math.ceil(colsRemaining / Math.abs(toRow - curRow));
let nextCol = findEmptyGridCol(nextRow, curCol, curCol + colsNow);
let curX = x(curCol), curY = y(curRow),
nextX = x(nextCol), nextY = y(nextRow);
let [distanceFromEdge, distanceOnEdge] =
perpendicular_coords(curX, curY, toX, toY, nextX, nextY);
let point = {curCol, curRow,
toCol, toRow,
nextCol, nextRow,
curX, curY, toX, toY, nextX, nextY,
edgeLength,
colsNow,
//wayCol, wayRow,
distance:-distanceFromEdge * 2,
weight:distanceOnEdge / edgeLength,
};
curCol = nextCol;
curRow = nextRow;
return point;
});
if (points.length === 0)
return [stubPoint];
return points;
}
【问题讨论】:
标签: cytoscape.js