使用D3,可以将语义缩放应用于径向树吗?

时间:2014-01-13 19:48:22

标签: javascript d3.js zoom

我正在使用D3 node link tree,我在尝试应用语义缩放时遇到了麻烦。

我已经花了一些时间烦恼,试图让它发挥作用 - 所以我想我会问这里,看看它是否有可能在我花更多时间之前...我不确定是否语义缩放是一种线性的东西。

修改 - 工作解决方案

这是我的工作解决方案。我没有在这里清理代码 - 但它应该给你一个想法。

http://codepen.io/toadums/pen/wjovC

1 个答案:

答案 0 :(得分:7)

由于在径向树中解释d.xd.y的方式不同,简单的“语义缩放”方法,让你让行为对象和尺度进行所有计算,并不是'工作。

树形布局计算的(x,y)坐标用于绘制径向树中距离中心的角度和距离。这些值不会直接转换为缩放行为创建的x和y坐标。因此,您不能只将缩放附加到缩放行为,在缩放时自动调整缩放域,然后使用缩放重新绘制点。

(P.S。我假设您只是想要一个普通的缩放来放大图形的一部分,而不是像Jason Davies'zoomable sunburst例子那样重新计算角度。)

回顾一下你的元素如何转换为初始布局:

  • 包含图表的<g>元素的翻译将(0,0)坐标定位在绘图区域的中心。

  • 每个节点组的旋转,根据布局中的d.x值(始终在0到360之间)计算,设置角度。

  • 然后(顺序很重要),每个节点组的转换根据来自的d.y值,沿着旋转的基线将其移离中心。布局根据所需的圆半径进行缩放。

请注意,径向树示例在树布局函数中执行所有缩放(通过调用size()方法) - 不使用缩放。

为了放大圆圈的某个部分,您需要:

  • 通过对<g>元素应用变换,将布局的中心转换到绘图中心以外的某个位置。

  • 使用<g>元素上的第二个转换来更改整个图像的比例(这也会缩放文本,圆圈大小等)

  • 根据比例因子更改每个节点的水平转换。

请注意,您只保留节点的旋转角度!

如果您不介意缩放文本和节点的大小,则将变换应用于<g>元素非常简单。

如果要在不增加单个元素大小的情况下缩放布局,则需要更改与布局中心的距离的计算方式。

要使中心的翻译正确:

  • 在缩放功能中,使用d3.event.translate访问整个图形所需翻译的(x,y)数组。

  • 使用此选项覆盖<g>元素上的转换,记住对于(0,0)的缩放转换,您仍希望<g>元素具有(宽度/ 2,高度/ 2)。所以你需要这样的东西:

    svg.attr("transform", "translate(" + (width/2 + d3.event.translate[0]) +
    "," + (height/2 + d3.event.translate[1]) + ")" );

  • 如果要直接缩放<g>元素,则必须在同一属性调用中设置两个转换,作为一个长字符串,并且您希望进行一些测试以查看是否它更自然地在翻译之前或之后应用比例(scale(2) translate(50)等于translate(100) scale(2),因为翻译坐标也被缩放)。比例因子可用d3.event.scale

要使距中心的距离(“y”变量)缩放正确:

  • 使用域[0,1]和范围[0,radius]创建径向比例。

  • 将树形布局的大小设置为“高度”为1,而不是直接使用半径。

  • 定位节点时,使用比例将布局中的d.y值(介于0和1之间)转换为转换中使用的实际径向距离。

    node.attr("transform", function(d) { return "rotate(" + (d.x - 90)
    + ")translate(" + radialScale(d.y) + ")"; })

  • 关于缩放行为,请勿附加任何比例!虽然您需要根据缩放调整径向比例,但您只想调整比例而不是将其翻译 - 所有翻译都将直接应用于定义圆心的<g>元素

  • 在缩放功能中,将径向刻度的域设置为[0, 1/d3.event.scale]。换句话说,如果缩放行为告诉我们将图像缩放2,我们希望绘图区域的中心和边缘之间的距离(范围,您不会更改)表示距离之间的距离的1/2。中心和树的边缘(域)。

  • 然后,使用与上面相同的语法重置各个节点组上的transformation属性。 (您将要使该匿名函数成为命名函数,因此您只需在代码的两个部分中传递函数名称。)

所以,我不知道所有额外的代码是否都算作“语义缩放”了。但它应该缩放你的图表。如果你的小提琴工作,请回来留下链接!