D3可缩放旭日不缩放(来自R的数据)

时间:2017-05-05 13:17:11

标签: javascript r d3.js zooming sunburst-diagram

我正在尝试调整一些代码,以便我可以在sunburst(使用D3)图表中绘制数据,并将来自R的数据作为数据帧。

除了缩放部分,当我点击(几乎)没有任何反应时,我的大部分工作正常。

在mouseOver上我得到了一个半径大于旭日的圆的一部分,以帮助强调我悬停的数据。这解释了arcHighlight变量。也可以注意到它不是使用我的比例ab构建的。我修改了原始代码以使用比例,我暂时离开了arcHighlight

经过一番挖掘,这question似乎表示我需要删除partition.size,因为我的尺度a和{{1}会照顾它}。我确实试过了,但如果我像这样评论尺寸部分,它就没有绘制任何东西:

b

点击功能结束时,我的高光圈不可见。这是正常的,但不要进行缩放。一旦我将鼠标移动到其他位置,我的高亮圆圈就会重新出现(正常,在鼠标悬停功能中进行颜色编码)。所以这一切都能正常工作而不会崩溃或冻结,只是缩放部分。我必须错过一些简单的东西,但无法弄清楚是什么。

感谢所有能够提供帮助的人。还请注意,我对JS很新,所以这可能只是一个非常简单的错误,如果是这样,我很抱歉。

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

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

点击功能:

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

和arcTween函数:

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

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

  }

我尝试改编的原始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);
            };
    }
  }

此函数位于.js文件中,不能与R一起使用。出于某种原因,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); }; }; } 指令冻结了我的图表而未缩放,因此我选择了return i

编辑1:R如何为这个旭日图表提供信息 我用于此的数据帧只有两列,第一列仅包含层次结构作为字符串(连字符分隔),第二列包含此类层次结构的出现次数。它看起来像这样:

(i==0)?...

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

buildhierarchy

1 个答案:

答案 0 :(得分:1)

看起来你没有返回将t作为参数的函数。您可以看到原始补间的返回数比您更改的版本多一个。

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