javascript - 使用 d3.js 拼出多层饼图效果

标签 javascript d3.js charts pie-chart

我有一个具有不同内半径的多层饼图,如下所示:

enter image description here

上面的饼图的代码可以在这里找到:

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

        var color = d3.scale.ordinal()
            .range(["cyan", "green", "blue", "brown", "violet", "orange", "purple"]);
    var arcMajor = d3.svg.arc()
        .outerRadius(function (d) {
            return radius - 20;
        })
        .innerRadius(0);
    //this for making the minor arc
    var arcMinor = d3.svg.arc()
        .outerRadius(function (d) {
            // scale for calculating the radius range([20, radius - 40])
            var s = scale((d.data.major - d.data.minor));
            if (s > radius - 20) {
                return radius - 20;
            }

            return scale(d.data.major - d.data.minor);
        })
        .innerRadius(0);
    var labelr = 260;
    var pie = d3.layout.pie()
        .sort(null)
        .value(function (d) {
            return d.major;
        });


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

    data = [{
        major: 500,
        minor: 250,
        grp: 1
    }, {
        major: 100,
        minor: 80,
        grp: 2
    }, {
        major: 100,
        minor: 50,
        grp: 3
    }, {
        major: 100,
        minor: 60,
        grp: 4
    }, {
        major: 100,
        minor: 10,
        grp: 5
    }];
    var scale = d3.scale.linear()
    .range([d3.min(data, function (d) {
        return d.minor;
    }), radius - 100 - d3.max(data, function (d) {
        return d.minor / d.major;
    })])
    //setting the scale domain
    .domain([d3.min(data, function (d) {
        return d.minor;
    }), d3.max(data, function (d) {
        return d.minor;
    })]);

    var g = svg.selectAll(".arc")
        .data(pie(data))
        .enter().append("g")
        .attr("class", "arc");
    g.append("svg:text")
.attr("transform", function (d) {
    var c = arcMajor.centroid(d),
        x = c[0],
        y = c[1],
        // pythagorean theorem for hypotenuse
        h = Math.sqrt(x * x + y * y);
    return "translate(" + (x / h * labelr) + ',' +
       (y / h * labelr) + ")";
})
.attr("dy", ".35em")
.attr("text-anchor", function (d) {
    // are we past the center?
    return (d.endAngle + d.startAngle) / 2 > Math.PI ?
        "end" : "start";
})
.text(function (d, i) { return d.value.toFixed(2); });
    //this makes the major arc
    g.append("path")
        .attr("d", function (d) {
            return arcMajor(d);
        })
        .style("fill", function (d) {
            return d3.rgb(color(d.data.grp));
        });

    //this makes the minor arcs
    g.append("path")
        .attr("d", function (d) {
            return arcMinor(d);
        })
        .style("fill", function (d) {
            return d3.rgb(color(d.data.grp)).darker(2);//for making the inner path darker
        });

http://jsfiddle.net/6e8aue0h/10/

我想为这个馅饼添加碎片功能。像这样:

enter image description here

我尝试使用 d3-pie 插件,但没有成功。

当您将鼠标悬停在特定部分上时,它应该会显示出饼图,如下图所示。 https://github.com/dansdom/plugins-d3-pie

在这种特殊情况下我该如何实现?

非常感谢。

最佳答案

在这里,我以类似的方式为主馅饼添加了片段效果,您可以为内部馅饼添加效果。我在变量上添加了圆弧

var arcOver = d3.svg.arc()
        .outerRadius(radius + 9);

以及主弧的 mouseenter 和 mouseout 函数。

.on("mouseenter", function(d) {

            d3.select(this)
               .attr("stroke","white")
               .transition()
               .duration(1000)
               .attr("d", arcOver)             
               .attr("stroke-width",6);
        })
        .on("mouseleave", function(d) {
            d3.select(this).transition()            
               .attr("d", arcMajor)
               .attr("stroke","none");
        })

这是示例。

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

        var color = d3.scale.ordinal()
            .range(["cyan", "green", "blue", "brown", "violet", "orange", "purple"]);

        var arcMajor = d3.svg.arc()
            .outerRadius(function (d) {
                return radius - 20;
            })
            .innerRadius(0);

		 var arcOver = d3.svg.arc()
        .outerRadius(radius + 9);
        //this for making the minor arc
        var arcMinor = d3.svg.arc()
            .outerRadius(function (d) {
                // scale for calculating the radius range([20, radius - 40])
                var s = scale((d.data.major - d.data.minor));
                if (s > radius - 20) {
                    return radius - 20;
                }

                return scale(d.data.major - d.data.minor);
            })
            .innerRadius(0);

	 var arcOverMin = d3.svg.arc()
        .outerRadius(radius - 90 );

		// Define the div for the tooltip
        var div = d3.select("body").append("div")	
            .attr("class", "tooltip")				
            .style("opacity", 0);
		
        var labelr = 260;
        var pie = d3.layout.pie()
            .sort(null)
            .value(function (d) {
                return d.major;
            });


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

        data = [{
            major: 500,
            minor: 250,
            grp: 1
        }, {
            major: 100,
            minor: 80,
            grp: 2
        }, {
            major: 100,
            minor: 50,
            grp: 3
        }, {
            major: 100,
            minor: 60,
            grp: 4
        }, {
            major: 100,
            minor: 10,
            grp: 5
        }];
        var scale = d3.scale.linear()
        .range([d3.min(data, function (d) {
            return d.minor;
        }), radius - 100 - d3.max(data, function (d) {
            return d.minor / d.major;
        })])
        //setting the scale domain
        .domain([d3.min(data, function (d) {
            return d.minor;
        }), d3.max(data, function (d) {
            return d.minor;
        })]);

        var g = svg.selectAll(".arc")
            .data(pie(data))
            .enter().append("g")
            .attr("class", "arc");
        g.append("svg:text")
    .attr("transform", function (d) {
        var c = arcMajor.centroid(d),
            x = c[0],
            y = c[1],
            // pythagorean theorem for hypotenuse
            h = Math.sqrt(x * x + y * y);
        return "translate(" + (x / h * labelr) + ',' +
           (y / h * labelr) + ")";
    })
    .attr("dy", ".35em")
    .attr("text-anchor", function (d) {
        // are we past the center?
        return (d.endAngle + d.startAngle) / 2 > Math.PI ?
            "end" : "start";
    })
    .text(function (d, i) { return d.value.toFixed(2); });
        //this makes the major arc
        g.append("path")
            .attr("d", function (d) {
                return arcMajor(d);
            })
        	   .on("mouseenter", function(d) {
           
            d3.select(this)
               .attr("stroke","white")
               .transition()
               .duration(1000)
               .attr("d", arcOver)             
               .attr("stroke-width",6);
            
               div.transition()		
                .duration(200)		
                .style("opacity", .9);		
              div.html(
                  '<a href= "http://facebook.com">' + // The first <a> tag
				 d.data.major +
				"</a>"
                  + "<br/>"  + d.data.minor)	
                .style("left", (d3.event.pageX) + "px")		
                .style("top", (d3.event.pageY - 28) + "px");	
           
        })
        .on("mouseleave", function(d) {
            d3.select(this).transition()            
               .attr("d", arcMajor)
               .attr("stroke","none");
        })
            .style("fill", function (d) {
                return d3.rgb(color(d.data.grp));
            });

        //this makes the minor arcs
        g.append("path")
            .attr("d", function (d) {
                return arcMinor(d);
            })
        	 .on("mouseenter", function(d) {
           
            d3.select(this)
               .attr("stroke","white")
               .transition()
               .duration(1000)
               .attr("d", arcOverMin)             
               .attr("stroke-width",6);
        })
        .on("mouseleave", function(d) {
            d3.select(this).transition()            
               .attr("d", arcMinor)
               .attr("stroke","none");
        })
            .style("fill", function (d) {
                return d3.rgb(color(d.data.grp)).darker(2);//for making the inner path darker
            });
.arc text {
    font: 10px sans-serif;
    text-anchor: middle;
}
.arc path {
    stroke: #fff;
}
div.tooltip {	
    position: absolute;			
    text-align: center;			
    width: 60px;					
    height: 28px;					
    padding: 2px;				
    font: 12px sans-serif;		
    background: lightsteelblue;	
    border: 0px;		
    border-radius: 8px;				
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

关于javascript - 使用 d3.js 拼出多层饼图效果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33991863/

相关文章:

javascript - 谷歌图表 : Chart within tooltip not displaying

javascript - For 循环中的 onClick 事件

javascript - touchableopacity onpress 函数未定义(不是函数)React Native

javascript - 使用 ">>>"运算符改进循环?

javascript - D3.js可视化-如何添加Y轴网格线

javascript - Google Visualization Charts API - 更改折线图上资源管理器功能的突出显示颜色

javascript 替换为具有特定 id 的正则表达式 img 标记,但其他属性可以是任何内容

Javascript 按键计算对象数组的百分比总计

javascript - nvd3js 中的堆积面积图 - X 轴溢出

ios - Swift iOS 图表 - 隐藏某些条形图值标签