D3可变焦森伯斯特无法变焦(来自R的数据) [英] D3 zoomable sunburst not zooming (with data from R)

查看:92
本文介绍了D3可变焦森伯斯特无法变焦(来自R的数据)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试修改一些代码,以便可以将旭日形图(使用D3)中的数据与来自R的数据作为数据帧一起绘制.

I'm trying to adapt some code so I can plot data in a sunburst (using D3) chart with data coming from R as a dataframe.

除缩放部分外,我大部分都可以正常工作,当我单击(几乎)时,什么也没发生.

I've got most of it working ok except the zooming part, when i click (almost) nothing happens.

在mouseOver上,我得到的一部分圆的半径大于朝阳半径,以帮助强调我所徘徊的数据.这解释了arcHighlight变量.也可以注意到它不是使用我的标尺ab构造的.我修改了原始代码以使用磅秤,并且现在保持了arcHighlight的状态.

On mouseOver I've got a portion of circle with a greater radius than the one for the sunburst to help emphasizing the data I'm hovering. This explains the arcHighlightvariable. Also one can notice it is not constructed using my scales a and b. I modifed the original code to use the scales, and I left the arcHighlightas is for now.

经过一番挖掘,这个问题似乎表明我需要删除partition.size,因为我的体重秤ab会照顾到它.我确实尝试过,但是如果我这样注释尺寸部分,则不会显示任何内容:

After a bit of digging around, this question seems to indicate that I need to delete the partition.sizesince it will be taken care of by my scales a and b. I did try that but it does not plot anything if I comment the size part like this :

  var partition = d3.layout.partition()
      //.size([2 * Math.PI, (radius - outerRadius) * (radius - outerRadius)])
      .value(function(d) { return d[x.options.valueField || "size"]; });

在单击功能结束时,我使突出显示的圆圈不可见.可以正常工作,但不进行缩放.一旦将鼠标移到其他位置,我的突出显示圆圈就会重新出现(正常,鼠标悬停功能中使用颜色编码).因此,这一切都可以正常工作,而不会崩溃或冻结,而只是缩放部分.我一定想念一些简单的事情,但不知道是什么.

At the end of the click function, I'm making my highlight circle invisible. That works correctly, but do not do the zooming. As soon as I move my mouse elsewhere, my highlight circle reappear (normal, color coded in the mouseover function). So it all works correctly without crashing or freezing, but just the zooming part. I must be missing something easy but can't figure out what.

感谢所有可能提供帮助的人.还请注意,我是JS的新手,所以这可能只是一个非常简单的错误,如果可以的话,我深表歉意.

Thanks for all of you guys who might be able to help out. Please also note that I'm pretty new to JS so it might just be a very simple mistake, my apologies if so.

我的代码(我认为是相关的...):

My code (what I think is relevant... ) :

  // Dimensions of sunburst
  var width = el.getBoundingClientRect().width - (x.options.legend.w ? x.options.legend.w : 75);
  var height = el.getBoundingClientRect().height - 70;
  var radius = Math.min(width, height) / 2;
  var outerRadius = radius/3.5; // reserved pixels all around the vis

  // Create scales
  var a = d3.scale.linear()
        .range([0, 2 * Math.PI]);

  var b = d3.scale.linear()
        .range([0, (radius - outerRadius)]);

  var vis = d3.select(el).select(".sunburst-chart").select("svg")
      .append("g")
      .attr("id", el.id + "-container")
      .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

  var partition = d3.layout.partition()
      .size([2 * Math.PI, (radius - outerRadius) * (radius - outerRadius)])
      .value(function(d) { return d[x.options.valueField || "size"]; });

  var arc = d3.svg.arc()
      .startAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, a(d.x/(2 * Math.PI)))); })
      .endAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, a((d.x+d.dx)/(2 * Math.PI)))); })
      .innerRadius(function(d) { return (d.dy == d.y) ? Math.max(0, b((Math.sqrt(d.y))/(radius - outerRadius))/3) : Math.max(0, b((Math.sqrt(d.y))/(radius - outerRadius))); })
      .outerRadius(function(d) { return Math.max(0, b((Math.sqrt(d.y + d.dy))/(radius - outerRadius))); });

  var arcHighlight = d3.svg.arc()
      .startAngle(function(d) { return d.x; })
      .endAngle(function(d) { return d.x + d.dx; })
      .innerRadius(function(d) { return 0; })
      .outerRadius(function(d) { return radius; });

  var highlight = vis.append("path")
        .attr("d", null)
        //.style("opacity", 0);
        .style("fill", "#eee"); 

  var path = vis.data([json]).selectAll("dataArc")
        .data(nodes)
        .enter().append("path")
        .attr("display", function(d) { return d.depth ? null : "none"; })
        .attr("d", arc)
        .attr("fill-rule", "evenodd")
        .style("fill", function(d) { return colors.call(this, d.name); })
        .style("opacity", 1)
        .on("mouseover", mouseover)
        //.on("mouseleave", mouseleave) // do not work
        .on("click", click);

  // Add the mouseleave handler to the bounding circle.
  d3.select(el).select("#"+ el.id + "-container").on("mouseleave", mouseleave);

点击功能:

  function click(d) {
    vis.selectAll("path")
        .transition('arc_tween') 
        .duration(1750)
        .attrTween("d", arcTween(d));

    highlight
        .transition()
        .duration(250)
        .attr("d", null);

  }

和arcTween函数:

and the arcTween function :

function arcTween(d) {

    var xd = d3.interpolate(a.domain(), [ (d.x/(2 * Math.PI)) , ((d.x+d.dx)/(2 * Math.PI)) ]);
    var yd = d3.interpolate(b.domain(), [ ((Math.sqrt(d.y))/(radius - outerRadius)) , (radius - outerRadius) ]);
    var yr = d3.interpolate(b.range(), [0, (radius - outerRadius)] );

    // For each node, return an interpolator function that D3 can use to transition.
    // The scales only need to be modified once per transition step, so only do this
    // when i = 0. In all cases the interpolator just re-applies the arc function,
    // which uses our newly updated scales to produce new curves.

    return function(d, i) {
        (i == 0) ?
            function(t) {
                a.domain(xd(t));
                b.domain(yd(t));
                return arc(d);
            } 
        : function(t) {
                return arc(d);
            };
    }
  }

我要适应的原始arcTween函数如下所示:

The original arcTween function I'm trying to adapt looks like this :

function arcTween(root) {

    var xd = d3.interpolate(x.domain(), [root.x, root.x + root.dx]);
    var yd = d3.interpolate(y.domain(), [root.y, 1]);
    var yr = d3.interpolate(y.range(), [root.y ? 20 : 0, r - outerRadius]);

    // For each node, return an interpolator function that D3 can use to transition.
    // The scales only need to be modified once per transition step, so only do this
    // when i = 0. In all cases the interpolator just re-applies the arc function,
    // which uses our newly updated scales to produce new curves.
    return function(d, i) {
        return i
            ? function(t) { return arc(d); }
        : function(t) { x.domain(xd(t)); y.domain(yd(t)).range(yr(t)); return arc(d); };
    };
}

此函数位于无法与R一起使用的.js文件中.出于某些原因,return i指令冻结了我的图表,但没有同时缩放,因此我选择了(i==0)?....

This function is in a .js file that does not work with R. For some reason the return i instruction is freezing my chart while not zooming either, hence my go with (i==0)?....

R如何喂养这张朝阳图 我为此使用的数据框只有两列,第一列仅包含层次结构作为字符串(连字符(连字符)),第二列包含此类层次结构的出现次数.看起来可能像这样:

Edit 1 : how R is feeding this sunburst chart The dataframe I use for this has only two columns, the first one containing only the hierarchy as a string (hyphen seperated) and the second column the number of occurences of such a hierarchy. It could look like this :

 search-search-search-product-product-product, 7311
 search-search-search-product-product-search, 2807
 search-search-search-product-search-account, 145
 search-search-search-product-search-end, 501
 search-search-search-product-search-home, 57
 search-search-search-product-search-other, 16
 search-search-search-product-search-product, 4559
 search-search-search-product-search-search, 2030
 search-search-search-search-account-account, 300
 search-search-search-search-account-end, 49

.JS文件中有一个buildhierarchy函数,该函数具有2列df并将其转换为适合分区的分层结构.这是代码:

In the .JS file, there is a buildhierarchy function that takes a 2 column df and transform it into a hierarchical structure suitable for partitioning. Here is the code :

function buildHierarchy(csv) {
  var root = {"name": "root", "children": []};
  for (var i = 0; i < csv.length; i++) {
    var sequence = csv[i][0];
    var size = +csv[i][1];
    if (isNaN(size)) { // e.g. if this is a header row
      continue;
    }
    var parts = sequence.split("-");
    var currentNode = root;
    for (var j = 0; j < parts.length; j++) {
      var children = currentNode["children"];
      var nodeName = parts[j];
      var childNode;
      if (j + 1 < parts.length) {
   // Not yet at the end of the sequence; move down the tree.
    var foundChild = false;
    for (var k = 0; k < children.length; k++) {
      if (children[k]["name"] == nodeName) {
        childNode = children[k];
        foundChild = true;
        break;
      }
    }
  // If we don't already have a child node for this branch, create it.
    if (!foundChild) {
      childNode = {"name": nodeName, "children": []};
      children.push(childNode);
    }
    currentNode = childNode;
      } else {
    // Reached the end of the sequence; create a leaf node.
    childNode = {"name": nodeName, "size": size};
    children.push(childNode);
      }
    }
  }
  return root;

};

推荐答案

似乎您没有返回以t为参数的函数.您会看到原始补间的收益比更改后的补间多.

It looks like you are not returning the function that takes t as an argument. You can see the original tween has one more return than your changed version has.

return function(d, i) {
        return (i == 0) ?
            function(t) {
                a.domain(xd(t));
                b.domain(yd(t));
                return arc(d);
            } 
        : function(t) {
                return arc(d);
            };
    }

这篇关于D3可变焦森伯斯特无法变焦(来自R的数据)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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