使用D3,语义缩放可以应用到径向树? [英] Using D3, can semantic zoom be applied to a radial tree?

查看:187
本文介绍了使用D3,语义缩放可以应用到径向树?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用D3 节点链接树,而且我无法尝试获取语义应用缩放。



我已经花了一点时间精力,试图让它工作 - 所以我想我会问这里,看看是否甚至可能在我花费之前更多时间...我不确定语义缩放是否只是一种线性的东西。



编辑 - 工作解决方案 >

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



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

解决方案

因为在径向树中解释不同的方式 dx dy 是简单的语义缩放方法,行为对象和尺度做所有的计算,不工作。



通过树布局计算的(x,y)坐标用于绘制径向树中距离中心的角度和距离。这些值不会直接转换为缩放行为创建的x和y坐标。所以你不能只是附加你的缩放到缩放行为,缩放域自动调整缩放,然后重新绘制你的点使用比例。



(PS I假设你只是想要一个正常的缩放来放大图表的一部分,而不是重新计算角度,如Jason Davies的



对于初始布局,您的元素是如何转换的:




  • < g> 元素上翻译,包含图形将(0,0)


  • 每个节点组上的旋转,根据 dx


  • 然后 (顺序很重要),a translate在每个节点组上,根据来自布局的 dy 值,沿着旋转后的基线将其从中心移开,该布局基于所需的圆半径进行缩放。 / p>




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



为了放大圆形的一部分,需要:




  • 通过对布局的中心进行变换,将布局的中心转换为除绘图中心以外的其他位置< g> 元素。


  • 元素上

  • $ b $

    进行第二次转换,整个图片(这也会缩放文字,圆形尺寸等)



$ b

$ b

请注意,你只留下节点的旋转角度!



如果您不介意缩放文字和节点大小,请将转换应用到< g> element是相当简单的。



如果你想放大布局而不增加单个元素的大小,你将需要改变距离计算布局的中心。



要获得中心翻译的正确性:




  • 您的缩放函数,使用 d3.event.translate 可访问整个图形所需转换的(x,y)数组。


  • 使用此选项覆盖< g> 元素上的变换, (0,0)的缩放转换仍然希望< g> 元素具有(width / 2,height / 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变量)的缩放比例:




  • domain [0,1] 和范围 [0,radius]


  • 将树布局的大小设置为height为1,而不是直接使用半径。


  • 定位节点时,使用scale将布局中的 dy 值转换为实际的径向距离



    node.attr(transform,function(d){returnrotate(+(dx - 90)

    +)translate(+ radialScale(dy)+);})


  • 在缩放行为上,不要附加任何缩放!虽然您需要根据缩放来调整径向缩放,但您只想调整缩放,而不是翻译它 - 所有翻译将直接应用于< g>


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


  • 然后,使用与上述相同的语法重置单个节点组上的变换属性。 (你想让匿名函数成为一个命名函数,所以你可以在代码的两个部分传递函数名。)




所以,我不知道这些额外的代码是否被视为语义缩放。但它应该放大你的图表。如果你让你的小提琴工作,回来,离开链接!


I am using the D3 node link tree, and I am having trouble trying to get semantic zoom applied to it.

I have already spent a bit of time fussing, trying to get it to work - so I thought I would ask here, to see if it is even possible before I spend more time... I am not sure if semantic zoom is a linear-only sort of thing.

Edit - Working Solution

Here is my working solution. I didnt clean up the code here - but it should give you an idea.

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

解决方案

Because of the different way d.x and d.y are interpreted in the radial tree, the simple "semantic zoom" approach, where you let the behaviour object and the scales do all the calculations, doesn't work.

The (x,y) coordinates calculated by the tree layout are used to plot angles and distance from the centre in a radial tree. Those values don't directly convert into the x and y coordinates that the zoom behaviour creates. So you can't just attach your scales to your zoom behaviour, have the scale domain automatically adjusted on zoom, and then replot your points using the scales.

(P.S. I'm assuming you just want a normal zoom to magnify a part of the graph, and not a re-calculation of angles like Jason Davies' zoomable sunburst example.)

A recap of how your elements are transformed for the initial layout:

  • A translate on the <g> element that contains the graph positions the (0,0) coordinate in the centre of the plotting area.

  • A rotation on each node group, calculated based on the d.x value from the layout (which is always between 0 and 360), sets the angle.

  • And then (order is important), a translate on each node group moves it away from the centre, along the rotated baseline, according to the d.y value from the layout which is scaled based on the desired radius of the circle.

Note that the radial tree example does all the scaling inside the tree layout function (by calling the size() method) -- no scales are used.

In order to zoom in on a section of the circle, you are going to need to:

  • Translate the centre of the layout to somewhere other than the centre of the plotting by applying a transform to the <g> element.

  • Either Change the scale of the entire image (this will also scale text, circle size, etc.) with a second transform on the <g> element

  • or change the horizontal translation of each node according to the scale factor.

Note that you leave the rotational angle of the nodes alone!

If you don't mind scaling text and the size of your nodes, applying the transforms to the <g> element is fairly straightforward.

If you want to zoom the layout without increasing the size of the individual elements, you're going to need to change how the distance from the centre of the layout is calculated.

To get the translation of the centre correct:

  • In your zoom function, use d3.event.translate to access the (x,y) array of the desired translation for the entire graph.

  • Use this to over-ride the transform on the <g> element, remembering that for a zoom translation of (0,0) you still want the <g> element to have a translation of (width/2, height/2). So you need something like:

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

  • If you were going to scale the <g> element directly, you would have to set both transformations in the same attribute call, as one long string, and you would want to do some tests to see if it worked more naturally to apply the scale before or after the translation (scale(2) translate(50) is equal to translate(100) scale(2), because the translation coordinates get scaled, too). The scale factor is available as d3.event.scale.

To get the scaling of the distance from the centre ("y" variable) correct:

  • Create a radial scale with domain [0,1] and range [0,radius].

  • Set the size of the tree layout to have "height" of 1 instead of using the radius directly.

  • When positioning your nodes, use the scale to convert the d.y value from the layout (which will be between 0 and 1) into the actual radial distance used in the transformation.

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

  • On your zoom behaviour, don't attach any scales! Although you'll need to adjust the radial scale based on zooming, you only want to adjust the scale and not translate it as well -- all translations will be applied directly to the <g> element that defines the centre of the circle.

  • In your zoom function, set the domain of the radial scale to [0, 1/d3.event.scale]. In other words, if the zoom behaviour tells us to scale the image by 2, we want the distance between the centre and edge of the plotting area (the range, which you don't change) to represent 1/2 the distance between the centre and the edge of the tree (the domain).

  • Then, reset the transformation attribute on the individual node groups using the same syntax as above. (You'll want to make that anonymous function a named function so you can just pass in the function name in both parts of your code.)

So, I don't know if all that extra code counts as "semantic zoom" any more. But it should zoom your graph. If you get your fiddle working, come back and leave a link!

这篇关于使用D3,语义缩放可以应用到径向树?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆