d3 圆圈在点击缩放时移动位置

d3 circles shifting position on click-to-zoom

我正在尝试使用一堆数据作为圆圈对 d3 图形实现缩放。数据由 1 个大圆圈和绘制在其中的许多小圆圈组成。我想点击较小的圆圈并放大它们。我正在使用 zoomable circle packing demo 的缩放变体。我不想直接使用演示代码,但我已经让它大部分工作了。

最初所有的圆圈都在正确的位置。但是,当我单击较小的圆圈时,它们会在缩放之前移动位置。当我点击白色圆圈向后缩放时,您可以看到它们现在已永久移动。当它缩放时,圆圈不会像在演示中那样放大到视口的中心。

我注意到当我注释掉转换线时

    node.attr("transform", function(d) { return "translate(" + (xscale(d.cx) - v[0]) * k + "," + (yscale(d.cy) - v[1]) * k + ")"; });

圆圈现在保持在正确的位置。它们的大小按应有的比例放大,但现在它们随着变大而相互融合,因为我不再翻译它们了。所以问题一定出在我的转换属性中,但我不知道是什么。或者这可能是我最初的看法?当我取消注释 zoomTo(view) 时,圆圈立即移动到不正确的位置。

我怎样才能让自己的位置保持在正确的位置?我如何让圆圈缩放到视点的中心?我以为我非常仔细地遵循了演示代码,但它并不完全正确。有任何想法吗?

我也希望坐标轴也能缩放,但我还没有深入解决我的问题。

这是我的 jsfiddle

还有我的完整 javascript 代码

function loadPlateDesign(){
var width = 400;
var height = 400;
var padding = 55;
var plateid = 7443;
var plateCen = {'ra': 230.99167, 'dec': 42.68736 };

var data = [{'name':7443,'color': 'white', 'cx': 0.0, 'cy': 0.0, 'r': 200},
    {'color': 'red', 'cx': 8.23066, 'cy': -134.645, 'ra':231.1,'dec':42.1,'name': '1901', 'r': 10.0, 
    'children':[{'color': 'red', 'cx': 8.23066, 'cy': -134.645, 'ra':231.1,'dec':42.1,'name': 'a', 'r': 2.0}]},
    {'color': 'blue', 'cx': -167.524, 'cy': -90.009, 'name': '711', 'r': 5.0}];

var xscale = d3.scale.linear().domain([330.,-330.]).range([0,400]);
var yscale = d3.scale.linear().domain([330.,-330.]).range([0,400]);

// initial focus and view
var focus = {'name':7443,'color': 'white', 'cx': 0.0, 'cy': 0.0, 'r': 200};
var view = [xscale(0.0),yscale(0.0),200*2];

// make the main svg element    
var svg = d3.select('#platedesign').append('svg')
    .attr('width',width+padding)
    .attr('height',height+padding);

// add the plate and ifu data   
var ifus=svg.selectAll('circle').data(data).enter().append('circle')
    .attr('id',function(d){return d.name;})
    .attr('cx',function(d,i){return xscale(d.cx);})
    .attr('cy',function(d,i){return yscale(d.cy);})
    .attr('r',function(d,i){return d.r;})
    .style('fill',function(d,i){return d.color;})
    .style('stroke','black')
    .on('click',function(d){
        if (focus != d) zoom(d), d3.event.stopPropagation();
    });

// add the axes 
var rascale = d3.scale.linear().domain([plateCen.ra+1.5,plateCen.ra-1.5]).range([0,400]);
var decscale = d3.scale.linear().domain([plateCen.dec+1.5,plateCen.dec-1.5]).range([0,400]);
xaxis = d3.svg.axis().scale(rascale).orient('bottom');
yaxis = d3.svg.axis().scale(decscale).orient('right').ticks(5);
svg.append('g').attr('class','x axis')
    .attr('transform','translate(0,'+(height+5)+')')
    .call(xaxis)
    .append('text')
    .attr('x',width/2)
    .attr('y',35)
    .style('text-anchor','middle')
    .text('RA');

svg.append('g').attr('class','y axis')
    .attr('transform','translate('+(width+5)+',0)')
    .call(yaxis)
    .append('text')
    .attr('transform','rotate(90)')
    .attr('x',height/2)
    .attr('y',-35)
    .style('text-anchor','middle')
    .text('Dec');

var node = svg.selectAll("circle");
//zoomTo(view);

function zoom(d){
    console.log('zooming to', d.name);
    var focus0 = focus; focus=d;
    var newview = [xscale(d.cx), yscale(d.cy), d.r*2+20];

    var transition = d3.transition()
        .duration(d3.event.altKey ? 7500 : 750)
        .tween('zoom', function(d){
            var i = d3.interpolateZoom(view, newview);
            return function(t) {zoomTo(i(t)); };
        });

}

function zoomTo(v) {
    var k = height / v[2]; view = v;
    console.log(height, v);
    node.attr("transform", function(d) { return "translate(" + (xscale(d.cx) - v[0]) * k + "," + (yscale(d.cy) - v[1]) * k + ")"; });
    ifus.attr("r", function(d) { return d.r * k; });
}

}

看来您在混合定位方法。您设置了初始 cxcy,但随后您放大了 transform。重新分解一下以使用 transform 完成所有定位修复它。我还发现您应该启动视图并对 d.cxd.cy 而不是 xscale(d.cx) 进行缩放计算。

function zoom(d){
    console.log('zooming to', d.name);
    var focus0 = focus; focus=d;
    var newview = [d.cx, d.cy, d.r*2+20];       
    var transition = d3.transition()
        .duration(d3.event.altKey ? 7500 : 750)
        .tween('zoom', function(d){
            var i = d3.interpolateZoom(view, newview);
            return function(t) {zoomTo(i(t)); };
        });     
}

function zoomTo(v) {
    var k = height / v[2]; view = v;
    console.log(height, v);
    node.attr("transform", function(d) { return "translate(" + xscale((d.cx - v[0]) * k) + "," + yscale((d.cy - v[1]) * k) + ")"; });
    ifus.attr("r", function(d) { return d.r * k; });
}

已更新 fiddle