按照我在 cmets 中建议的方向,结果如下:
https://jsfiddle.net/xdk5ehcr/
我没有使用旋转和平移来定位节点,而是创建了两个基于三角函数的函数来根据数据 (x,y) 值计算水平和垂直位置,这些值被视为极坐标。
然后我必须设置鱼眼功能以将我的定位功能用作“访问器”功能,而不是直接读取d.x 和d.y。不幸的是,您用于鱼眼的基本插件不包括获取和设置 x/y 访问器函数的方法,因此我也必须对其进行修改。我很惊讶它还没有在代码中。这是大多数 d3 布局对象的标准功能。
(当我设置好 github 后,我将不得不发出拉取请求来添加它。不过,我需要弄清楚鱼眼缩放/缩放功能是如何工作的——我从这个示例中删除了它因为你没有使用它。)
定位功能如下:
function getHPosition(d){
//calculate the transformed (Cartesian) position (H, V)
//(without fisheye effect)
//from the polar coordinates (x,y) where
//x is the angle
//y is the distance from (radius,radius)
//See http://www.engineeringtoolbox.com/converting-cartesian-polar-coordinates-d_1347.html
return (d.y)*Math.cos(d.x);
}
function getVPosition(d){
return (d.y)*Math.sin(d.x);
};
这些函数用于设置节点和链接的原始位置,然后一旦鱼眼进入,它就会在内部使用这些函数,将结果(如果合适,会失真)返回为d.fisheye.x 和d.fisheye.y。
例如,对于意味着投影设置d3.svg.diagonal 函数的链接,如下所示进行初始化:
var diagonal = d3.svg.diagonal()
.projection(function(d) {
return [getHPosition(d), getVPosition(d)];
});
但是像这样更新:
diagonal.projection(function(d) {
d.fisheye = fisheye(d);
return [d.fisheye.x, d.fisheye.y];
});
还有一些其他的小变化:
我稍微简化了绘图区域的尺寸。
我添加了一个带有pointer-events:all; 的背景矩形,这样当鼠标在节点和空白背景之间移动时,鱼眼不会打开和关闭。
我没有打扰旋转文本(因为节点组不再旋转,默认情况下不会发生),但您可以轻松地在单个文本上添加旋转转换元素。
最后,这个问题让我感到困扰的时间比我想承认的要长,对于 Javascript 三角函数,角度必须以 弧度 为单位。无法弄清楚为什么我的布局是so ugly, with overlapping lines。我认为这与在 d3.svg.diagonal() 和 d3.svg.diagonal.radial() 之间切换有关,并花了很多时间尝试做逆触发和各种事情......