如何更改 d3 sunburst 图表的缩放功能?

How can I alter the zooming capability on a d3 sunburst chart?

我正在尝试改变旭日图上的传统缩放功能。传统上,当您单击一个分区时,该分区会增长到覆盖 100% 的基础层,而同一层上的所有其他分区都会消失。所选分区的子项全部增长以填充新创建的 space。

我当前的代码正是我上面所说的。我想更改我的代码以允许所选分区仅占据基础层的 75%。子元素将增长以覆盖这个新的 space,但剩余的 25% 仍将包含所有其他未选择的分区。

我曾尝试更改从 d3.interpolate() 返回的 't' 值,但结果无法预料。

希望我的描述清楚。

有没有人对此有任何想法?

<script>

var width = 960,
height = 700,
radius = Math.min(width, height) / 2;

var x = d3.scale.linear()
.range([0, 2 * Math.PI]);

var y = d3.scale.linear()
.range([0, radius]);

var color = d3.scale.category20c();

function percent(d) {
    var percentage = (d.value / 956129) * 100;
    return percentage.toFixed(2);
}

var tip = d3.tip()
    .attr('class', 'd3-tip')
    .offset([-10, 0])
    .html(function(d) {
return "<strong>" + d.name + "</strong> <span style='color:red'>" + percent(d) + "%</span>";
  })

var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
  .append("g")
.attr("transform", "translate(" + width / 2 + "," + (height / 2 + 10) + ")");

svg.call(tip);

var partition = d3.layout.partition()
.value(function(d) { return d.size; });

var arc = d3.svg.arc()
.startAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x))); })
.endAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x + d.dx))); })
.innerRadius(function(d) { return Math.max(0, y(d.y)) })
.outerRadius(function(d) { return Math.max(0, y(d.y + d.dy)) });

d3.json("flare.json", function(error, root) {
  var g = svg.selectAll("g")
  .data(partition.nodes(root))
.enter().append("g");

  var path = g.append("path")
.attr("d", arc)
// .attr("stroke", 'black')
// .style("fill", function(d) { return color((d.children ? d : d.parent).name); })
.style("fill", function(d, i) {
    return color(i);
})
.on("click", click)
.on('mouseover', tip.show)
.on('mouseout', tip.hide);

  var text = g.append("text")
.attr("transform", function(d) { return "rotate(" + computeTextRotation(d) + ")"; })
.attr("x", function(d) { return y(d.y); })
.attr("dx", "6") // margin
.attr("dy", ".35em") // vertical-align
.text(function(d) {
    if (percent(d) > 1.35) {
        return d.name;
    }

})
.attr('font-size', function(d) {
    if (d.value < 100000) {
        return '10px'
    } else {
        return '20px';
    }
})
.on("click", click)
.on('mouseover', tip.show)
.on('mouseout', tip.hide);

  function click(d) {
console.log(d)
// fade out all text elements
text.transition().attr("opacity", 0);

path
    .transition()
    .duration(750)
    .attrTween("d", arcTween(d))
    .each("end", function(e, i) {
      // check if the animated element's data e lies within the visible angle span given in d
      if (e.x >= d.x && e.x < (d.x + d.dx)) {
        // get a selection of the associated text element
        var arcText = d3.select(this.parentNode).select("text");
        // fade in the text element and recalculate positions
        arcText.transition().duration(750)
          .attr("opacity", 1)
          .attr("transform", function() { return "rotate(" + computeTextRotation(e) + ")" })
          .attr("x", function(d) { return y(d.y); });
      }
  });
  }
});

d3.select(self.frameElement).style("height", height + "px");

// Interpolate the scales!
function arcTween(d) {
console.log(d.name, x.domain())
console.log(d.name, y.domain())
console.log(d.name, y.range())
  var xd = d3.interpolate(x.domain(), [d.x, d.x + d.dx]),
  yd = d3.interpolate(y.domain(), [d.y, 1]),
  yr = d3.interpolate(y.range(), [d.y ? 20 : 0, radius]);
  return function(d, i) {
return i
    ? function(t) { return arc(d); }
    : function(t) {
        console.log(t)
        x.domain(xd(t));
        y.domain(yd(t)).range(yr(t));
        return arc(d);

    };
  };
}

function computeTextRotation(d) {
  return (x(d.x + d.dx / 2) - Math.PI / 2) / Math.PI * 180;
}

我在这里找到了解决方案:https://bl.ocks.org/mbostock/1306365。此示例在不删除兄弟节点的情况下管理缩放。