Javascript 如何旋转D3图表,使选定的圆弧位于底部?

Javascript 如何旋转D3图表,使选定的圆弧位于底部?,javascript,d3.js,pie-chart,Javascript,D3.js,Pie Chart,我正在尝试开发一个应用程序,用户可以点击D3饼图,查看与选择相关的信息。如何旋转圆弧,使单击的圆弧位于底部?单击的圆弧的中心应位于底部?我一直在通过选择arc组来旋转馅饼,但我希望能有任何关于如何实现这一点的想法。 这是我到目前为止的一些代码 var self = this; var instanceId = Math.floor(Math.random() * 100000); var margin = { top: 5, right: 15

我正在尝试开发一个应用程序,用户可以点击D3饼图,查看与选择相关的信息。如何旋转圆弧,使单击的圆弧位于底部?单击的圆弧的中心应位于底部?我一直在通过选择arc组来旋转馅饼,但我希望能有任何关于如何实现这一点的想法。 这是我到目前为止的一些代码

 var self = this;
    var instanceId = Math.floor(Math.random() * 100000);

    var margin = {
        top: 5,
        right: 15,
        bottom: 50,
        left: 20
    };

    self.width = this.htmlElement.parentElement.parentElement.offsetWidth - margin.right - margin.left;
    self.height =   window.innerHeight / 3 ;
    self.curAngle = 0;

    self.svgParent.html("<h4 style='color:green;'>Sponsors </h4><br>");

    // Update data for the chart
    self.updateChartData = function () {

        if(!self.svg) {
            this.svg = this.svgParent
                .classed("svg-container", true)
                .append("svg")
                .attr("preserveAspectRatio", "xMinYMin meet")
                .attr("viewBox", "0 0 " + this.width + " " + this.height)
                .append("g")
                .classed("svg-content-responsive", true);
                //.attr("transform", "translate(" + this.width / 2 + "," + this.height / 2 + ")");
        }

        var svgg = this.svg
          .append("g")
          .classed("svg-content-responsive", true)
          .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

        self.svg.selectAll(".arctext").remove();
        self.svg.selectAll(".pie-widget-total-label").remove();

        var pie = d3.pie().sort(sort)(self.selectedData.map(function (d: any) {
            return d.count;
        }));

        var path = d3.arc()
            .outerRadius(radius)
            .innerRadius(radius / 2);

        var outsideLabel = d3.arc()
            .outerRadius(radius * 0.9)
            .innerRadius(radius * 0.9);

        var middleLabel = d3.arc()
            .outerRadius(radius * 0.75)
            .innerRadius(radius * 0.75);

        var insideLabel = d3.arc()
            .outerRadius(radius * 0.6)
            .innerRadius(radius * 0.6);

        var g = self.svg
            .attr("width", self.width + margin.left + margin.right)
            .attr("height", self.height + margin.top + margin.bottom)
            .append("g")
            .attr("transform", "translate(" + self.width / 2 + "," + self.height / 2 + ")");

        var defs = g.append("defs");

        var lightGradients = defs.selectAll(".arc")
            .data(pie)
            .enter()
            .append("radialGradient")
            .attr("id", function (d: any) {
                return "lightGradient-" + instanceId + "-" + d.index;
            })
            .attr("gradientUnits", "userSpaceOnUse")
            .attr("cx", "0")
            .attr("cy", "0")
            .attr("r", "120%");

        var darkGradients = defs.selectAll(".arc")
            .data(pie)
            .enter()
            .append("radialGradient")
            .attr("id", function (d: any) {
                return "darkGradient-" + instanceId + "-" + d.index;
            })
            .attr("gradientUnits", "userSpaceOnUse")
            .attr("cx", "0")
            .attr("cy", "0")
            .attr("r", "120%");

        lightGradients.append("stop")
            .attr("offset", "0%")
            .attr("style", function (d: any) {
                return "stop-color: " + d3.color(color(d.index)) + ";";
            });

        lightGradients.append("stop")
            .attr("offset", "100%")
            .attr("style", function (d: any) {
                return "stop-color: black;";
            });

        darkGradients.append("stop")
            .attr("offset", "0%")
            .attr("style", function (d: any) {
                return "stop-color: " + d3.color(color(d.index)).darker(0.5) + ";";
            });

        darkGradients.append("stop")
            .attr("offset", "100%")
            .attr("style", function (d: any) {
                return "stop-color: black;";
            });

        self.tooltip = d3.select("body")
            .append("div")
            .attr("class", "pie-widget-tooltip")
            .style("opacity", 0);

        self.arc = g.selectAll(".arc")
            .data(pie)
            .enter()
            .append("g")
            .attr("class", "arc");

        var arcpath = self.arc.append("path")
            .attr("id", function (d: any) {
                return d.index;
            })
            .attr("d", path)
            .attr("stroke", "white")
            .attr("stroke-width", "2px")
            .attr("fill", function (d: any) {
                return "url(#lightGradient-" + instanceId + "-" + d.index + ")";
            })
            .on("click", function (d: any) {
                console.log("About to send::::" + getStudyLabel(d.index));
                self.selectedIndustryTypeService.sendMessage(getStudyLabel(d.index));
                self.showDialog();
                self.rotateChart();
             })

            .transition()
            .duration(function(d:any, i:any) {
                return i * 800;
            })
            .attrTween('d', function(d:any) {
                var i = d3.interpolate(d.startAngle + 0.1, d.endAngle);
                return function (t: any) {
                    d.endAngle = i(t);
                    return path(d);
                }
            });

        function arcTween(a: any) {
            var i = d3.interpolate(this._current, a);
            this._current = i(0);
            return function(t: any) {
                return path(i(t));
            };
        }

        var gtext = self.svg
            .append("g")
            .attr("transform", "translate(" + self.width / 2 + "," + self.height / 2 + ")");

        var arctext = gtext.selectAll(".arctext")
            .data(pie)
            .enter()
            .append("g")
            .attr("class", "arctext");

        var primaryLabelText = arctext.append("text")
          .on("click", function (d: any) {
            console.log("About to send::::" + getStudyLabel(d.index));
            self.selectedIndustryTypeService.sendMessage(getStudyLabel(d.index));
            self.showDialog();
          })
            .transition()
            .duration(750)
            .attr("transform", function (d: any) {
                return "translate(" + middleLabel.centroid(d) + ")";
            })
            .attr("dy", "-0.75em")
            .attr("font-family", "sans-serif")
            .attr("font-size", "15px")
            .attr("class", "sponsor-pie-widget-label")
            .text(function (d: any) {
                if (d.endAngle - d.startAngle < 0.3) {
                    return "";
                } else {
                    return getStudyLabel(d.index);
                }
            });

        var secondaryLabelText = arctext.append("text")
          .on("click", function (d: any) {
            console.log("About to send::::" + getStudyLabel(d.index));
            self.selectedIndustryTypeService.sendMessage(getStudyLabel(d.index));
            self.showDialog();
          })
            .transition()
            .duration(750)
            .attr("transform", function (d: any) {
                return "translate(" + middleLabel.centroid(d) + ")";
            })
            .attr("dy", "0.75em")
            .attr("font-family", "sans-serif")
            .attr("font-size", "10px")
            .attr("class", "sponsor-pie-widget-label")
            .text(function (d: any) {
                if (d.endAngle - d.startAngle < 0.3) {
                    return "";
                } else {
                    return getPatientsLabel(d.index);
                }
            });

        var n = 0;
        for (var i = 0; i < self.selectedData.length; i++) {
            n = n + this.selectedData[i]["count"];
        }
        var total = self.svg
            .append("g")
            .attr("transform", "translate(" + (self.width / 2 - 20 ) + "," + self.height / 2 + ")")
        total.append("text")
            .attr("class", "pie-widget-total-label")
            .text("Total\r\n" + n);
    }.bind(self);


    self.showDialog = function() {
        this.router.navigateByUrl('/myRouteName');
    }.bind(self);

    self.rotateChart = function() {
      self.arc.attr("transform", "rotate(-45)");
    }.bind(self);

可以通过适当地更改圆弧的起点/终点角度来旋转圆弧,但这将比需要的更复杂

一个更简单的解决方案是只旋转一个容纳整个饼图的g,同时以另一种方式旋转任何标签,使其保持水平

我刚刚使用了中的规范饼图作为示例:

var svg=d3.selectsvg, 宽度=+svg.attrwidth, 高度=+svg.attrheight, 半径=数学最小宽度,高度/2, g=svg.appendg.attrtransform,translate+width/2+,+height/2+; var color=d3.标度标准[98abc5、8a89a6、7b6888、6b486b、a05d56、d0743c、ff8c00];
var data=[{age:太棒了!谢谢Andrew,我从这个答案中学到了一些东西。我无法让标签的转换正常工作。我在这里发布了另一个问题:。如果你能花点时间看看,那将非常有帮助。谢谢!