Javascript d3日暴图选择旋转不工作

Javascript d3日暴图选择旋转不工作,javascript,d3.js,svg,data-visualization,sunburst-diagram,Javascript,D3.js,Svg,Data Visualization,Sunburst Diagram,我正在创建一个d3太阳暴流图,它需要集成一个选择旋转,如下图所示:带有选择扭曲(仅部分缩放到选定路径)。我创建了一个JSFIDLE:它突出了我将两者结合起来的尝试。这张图表会扭曲和旋转,但旋转是不可预测的。我希望所选路径旋转到顶部12点钟位置,而不管它在图形上的位置如何(如第一个链接所示)。如有任何建议,将不胜感激 d3.json("flare.json", function(error, root) { if (error) throw error; var g = svg.selectAl

我正在创建一个d3太阳暴流图,它需要集成一个选择旋转,如下图所示:带有选择扭曲(仅部分缩放到选定路径)。我创建了一个JSFIDLE:它突出了我将两者结合起来的尝试。这张图表会扭曲和旋转,但旋转是不可预测的。我希望所选路径旋转到顶部12点钟位置,而不管它在图形上的位置如何(如第一个链接所示)。如有任何建议,将不胜感激

d3.json("flare.json", function(error, root) {
if (error) throw error;

var g = svg.selectAll("g")
    .data(partition.nodes(root))
    .enter().append("g");

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

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) {
        return d.name;
    })
.attr('font-size', function(d) {
    if (d.value < 100000) {
        return '10px'
    } else {
        return '20px';
    }
})
.on("click", magnify);

var innerG = d3.selectAll("g.inner");



// Distort the specified node to 80% of its parent.
function magnify(node) {
    text.transition().attr("opacity", 0);
    spin(node);

    if (parent = node.parent) {
        var parent,
            x = parent.x,
            k = 0.8;
        console.log(x)
        parent.children.forEach(function(sibling) {
            x += reposition(sibling, x, sibling === node
              ? parent.dx * k / node.value
              : parent.dx * (1 - k) / (parent.value - node.value));
        });
    } else {
        reposition(node, 0, node.dx / node.value);
    }

    path.transition()
    .duration(750)
    .attrTween("d", arcTween)
    .each("end", function(e, i) {
      // check if the animated element's data e lies within the visible angle span given in node
        if (e.x >= node.x && e.x < (node.x + node.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);
            });
        }
    });

}

function spin(d) {
    var newAngle = - (d.x + d.dx / 2);

    innerG
      .transition()
        .duration(1500)
        .attr("transform", "rotate(" + ((180 / Math.PI * newAngle) - 90) + ")");

    path
      .classed("selected", function (x) { return d.name == x.name; });
}

// Recursively reposition the node at position x with scale k.
function reposition(node, x, k) {
    // console.log(node)
    node.x = x;
    if (node.children && (n = node.children.length)) {
        var i = -1, n;
        while (++i < n) x += reposition(node.children[i], x, k);
    }
    return node.dx = node.value * k;
}

// Stash the old values for transition.
function stash(d) {
    d.x0 = d.x;
    d.dx0 = d.dx;
}

// Interpolate the arcs in data space.
function arcTween(a) {
    var i = d3.interpolate({x: a.x0, dx: a.dx0}, a);
    return function(t) {
        var b = i(t);
        a.x0 = b.x;
        a.dx0 = b.dx;
        return arc(b);
    };
};
});
d3.json(“flare.json”,函数(错误,根){
如果(错误)抛出错误;
var g=svg.selectAll(“g”)
.data(分区.节点(根))
.enter().append(“g”);
路径=g.append(“路径”)
.attr(“d”,弧)
.style(“fill”,函数(d){返回颜色((d.children?d:d.parent).name);})
。打开(“单击”,放大)
//.on('mouseover',tip.show)
//.on('mouseout',tip.hide)
.每个(储藏);
var text=g.append(“文本”)
.attr(“transform”,函数(d){return“rotate”(“+computeextrotation(d)+”);})
.attr(“x”,函数(d){返回y(d.y);})
.attr(“dx”,“6”)//保证金
.attr(“dy”,“.35em”)//垂直对齐
.文本(功能(d){
返回d.name;
})
.attr('font-size',函数(d){
如果(d.值<100000){
返回“10px”
}否则{
返回'20px';
}
})
。打开(“单击”,放大);
var innerG=d3。选择全部(“g.inner”);
//将指定节点扭曲为其父节点的80%。
功能放大(节点){
text.transition().attr(“不透明度”,0);
自旋(节点);
if(parent=node.parent){
var父级,
x=父级.x,
k=0.8;
console.log(x)
parent.children.forEach(函数(同级){
x+=重新定位(同级,x,同级==节点
?parent.dx*k/node.value
:parent.dx*(1-k)/(parent.value-node.value));
});
}否则{
重新定位(节点,0,node.dx/node.value);
}
path.transition()
.持续时间(750)
.attrTween(“d”,arcTween)
.每个(“结束”,功能(e,i){
//检查动画元素的数据e是否位于节点中给定的可见角度范围内
如果(e.x>=node.x&&e.x<(node.x+node.dx)){
//获取关联文本元素的选择
var arcText=d3.select(this.parentNode).select(“text”);
//淡入文本元素并重新计算位置
arcText.transition()持续时间(750)
.attr(“不透明度”,1)
.attr(“transform”,function(){return”rotate(“+ComputeExtratation(e)+”)})
.attr(“x”,函数(d){
返回y(d.y);
});
}
});
}
函数自旋(d){
var newAngle=-(d.x+d.dx/2);
innerG
.transition()
.持续时间(1500)
.attr(“变换”、“旋转”(+((180/Math.PI*newAngle)-90)+”);
路径
.classed(“selected”,函数(x){返回d.name==x.name;});
}
//使用比例k递归地将节点重新定位到位置x。
函数重新定位(节点,x,k){
//console.log(节点)
节点x=x;
if(node.children&(n=node.children.length)){
变量i=-1,n;
而(++i
经过多次修补,我终于找到了答案。我不知道这是否是最好的解决方案,但它是有效的

我设置了一个x和y变量,如下所示:

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

var y = d3.scale.linear()
    .range([0, radius]);
然后我像这样设置我的弧:

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)) })
    .cornerRadius(function(d) { return 5;});
上面是我最初的JSFIDLE示例

当调用我最初的spin函数(onClick)时,它的运行方式如下:

function spin(d) {
        var newAngle = - (d.x + d.dx / 2);
        console.log('newAngle', newAngle)

        innerG
          .transition()
            .duration(1500)
            .attr("transform", "rotate(" + ((180 / Math.PI * newAngle) - 90) + ")");


    path
      .classed("selected", function (x) { return d.name == x.name; });
}
这让我产生了一种不可预测的幻觉。经过一点修改后,我意识到如果我通过前面实例化的x变量运行自旋变换,然后单击自旋两次,每次都会修正到-90度。此时,我将-90放在转换上,并创建了一个promise/then函数来运行它两次:

function spin(d) {

    var spin1 = new Promise (function(resolve, reject) {
        var newAngle = - x(d.x + d.dx / 2);
        console.log('newAngle', newAngle)

        innerG
          .transition()
            .duration(1500)
            .attr("transform", "rotate(" + ((180 / Math.PI * newAngle)) + ")");
            resolve("Success!");
    });

    spin1.then(function() {
        var newerAngle = - x(d.x + d.dx / 2);
        console.log('newerAngle', newerAngle)

        innerG
          .transition()
            .duration(1500)
            .attr("transform", "rotate(" + ((180 / Math.PI * newerAngle)) + ")");
    })

    path
      .classed("selected", function (x) { return d.name == x.name; });
}

这可能有点老套,但效果很好。在这里查看最终结果:

经过大量的修补,我终于找到了答案。我不知道这是否是最好的解决方案,但它是有效的

我设置了一个x和y变量,如下所示:

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

var y = d3.scale.linear()
    .range([0, radius]);
然后我像这样设置我的弧:

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)) })
    .cornerRadius(function(d) { return 5;});
上面是我最初的JSFIDLE示例

当调用我最初的spin函数(onClick)时,它的运行方式如下:

function spin(d) {
        var newAngle = - (d.x + d.dx / 2);
        console.log('newAngle', newAngle)

        innerG
          .transition()
            .duration(1500)
            .attr("transform", "rotate(" + ((180 / Math.PI * newAngle) - 90) + ")");


    path
      .classed("selected", function (x) { return d.name == x.name; });
}
这让我产生了一种不可预测的幻觉。经过一点修改后,我意识到如果我通过前面实例化的x变量运行自旋变换,然后单击自旋两次,每次都会修正到-90度。此时,我将-90放在转换上,并创建了一个promise/then函数来运行它两次:

function spin(d) {

    var spin1 = new Promise (function(resolve, reject) {
        var newAngle = - x(d.x + d.dx / 2);
        console.log('newAngle', newAngle)

        innerG
          .transition()
            .duration(1500)
            .attr("transform", "rotate(" + ((180 / Math.PI * newAngle)) + ")");
            resolve("Success!");
    });

    spin1.then(function() {
        var newerAngle = - x(d.x + d.dx / 2);
        console.log('newerAngle', newerAngle)

        innerG
          .transition()
            .duration(1500)
            .attr("transform", "rotate(" + ((180 / Math.PI * newerAngle)) + ")");
    })

    path
      .classed("selected", function (x) { return d.name == x.name; });
}
这可能有点老套,但效果很好。在此处查看最终结果: