简体   繁体   English

D3可变焦森伯斯特无法变焦(来自R的数据)

[英]D3 zoomable sunburst not zooming (with data from 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. 我正在尝试修改一些代码,以便可以将旭日形图(使用D3)中的数据与来自R的数据作为数据帧一起绘制。

I've got most of it working ok except the zooming part, when i click (almost) nothing happens. 除缩放部分外,我大部分都可以正常工作,当我单击(几乎)时,什么也没有发生。

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. 在mouseOver上,我得到的一部分圆的半径大于朝阳半径,以帮助强调我所徘徊的数据。 This explains the arcHighlight variable. 这解释了arcHighlight变量。 Also one can notice it is not constructed using my scales a and b . 还可以注意到它不是使用我的标度ab构造的。 I modifed the original code to use the scales, and I left the arcHighlight as is for now. 我修改了原始代码以使用比例尺,并且现在就离开了arcHighlight

After a bit of digging around, this question seems to indicate that I need to delete the partition.size since it will be taken care of by my scales a and b . 经过一番挖掘之后,这个问题似乎表明我需要删除partition.size因为它将由我的秤ab来照顾。 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. 我肯定想念一些简单的事情,但不知道是什么。

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. 另请注意,我是JS的新手,所以这可能只是一个非常简单的错误,如果可以的话,我深表歉意。

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);

The click function : 点击功能:

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

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

  }

and the arcTween function : 和arcTween函数:

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);
            };
    }
  }

The original arcTween function I'm trying to adapt looks like this : 我尝试适应的原始arcTween函数如下所示:

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); };
    };
}

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一起使用的.js文件中。出于某种原因, return i指令冻结了我的图表,同时也不进行缩放,因此我选择了(i==0)?...

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. 编辑1:R如何为这张旭日形图提供数据我为此使用的数据框只有两列,第一列仅包含层次结构作为字符串(连字符分隔),第二列包含该层次结构的出现次数。 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

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. 在.JS文件中,有一个buildhierarchy函数,该函数采用2列df并将其转换为适合分区的层次结构。 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;

};

It looks like you are not returning the function that takes t as an argument. 看来您没有返回以t为参数的函数。 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);
            };
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM