d3.behavior.zoom() 将图形移动到角落而不是中心

d3.behavior.zoom() moves graph to corner instead of center

我想为我的朝阳效果添加鼠标滚轮缩放功能:
我所做的是编辑了这段代码:

var zoom = d3.behavior.zoom()
    .scaleExtent([1, 10])
    .on("zoom", zoomed);

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

function zoomed() {
  svg.attr('transform', 'translate(' + d3.event.transform.x + ',' + d3.event.transform.y + ') scale(' + d3.event.scale + ')');
  //svg.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}

问题是,当页面加载时一切似乎都正常,但是当使用鼠标滚轮滚动时,朝阳最终出现在左上角:

我能够通过更改此代码来解决此问题:

function zoomed() {
  svg.attr("transform", "translate(" + width/2 + "," + height * .52 + ")scale(" + d3.event.scale + ")");
}

旭日纹现在停留在中间,但是这不会缩放到光标所在的位置,也不允许用户进一步缩小。
有什么建议可以缩放到光标位置(如第一个代码示例中所示)而左上角的朝阳不消失吗?

完整代码参见 JSfiddle,它在这里不起作用,但是 运行 它在本地确实有效。

d3.event.translate returns 一个数组。因此,如果您想添加这些值(width/2height/2),您必须单独添加它们:

function zoomed() {
    svg.attr('transform', 'translate(' + (d3.event.translate[0] + width / 2) +
        ',' + (d3.event.translate[1] + height / 2) + ') scale(' + d3.event.scale + ')');
}

或者,如果您想使用原来的缩放功能...

function zoomed() {
    svg.attr("transform", "translate(" + d3.event.translate +
        ")scale(" + d3.event.scale + ")");
}

...只是打破 svg 选择,为组分配另一个名称:

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

var foo = svg.append("g")
    .attr("transform", "translate(" + width / 2 + "," + height * .52 + ")")
    .call(zoom);

我在 Zoomed 函数中使用标准 d3.event.translate 和 d3.event.scale,如下所示:

function zoomed() {
svg.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")");
}

一切正常,除了当我第一次滚动时整个旭日跳到左上角。我把它拖回中间后它自己纠正了,但是很烦人。

我为此苦苦挣扎了几个小时。最终我通过更改 svg 上的 viewBox 属性解决了这个问题:

.attr({viewBox: "" + (-width / 2) + " " + (-height / 2) + " " + width + " " + height})

我从这个例子中得到了灵感:Basic Sunburst