【问题标题】:Piece out effect for Multilayer pie Chart using d3.js使用 d3.js 对多层饼图进行拼图效果
【发布时间】:2015-11-30 15:14:18
【问题描述】:

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

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

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/

我想为这个馅饼添加拼图功能。像这样:

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

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

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

非常感谢。

【问题讨论】:

    标签: javascript d3.js charts pie-chart


    【解决方案1】:

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

    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;				
    }
    &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"&gt;&lt;/script&gt;

    【讨论】:

    • 非常感谢您的回复。如何将这种效果添加到内弧?并用 URL 显示一些文本?
    • 对于minner arc,你只需要像我对major arc所做的那样处理mouseenter和mouseout事件。您想在哪里添加带有 URL 的文本?
    • 我想添加饼图部分的文本(比如出现在这个特定饼图中的数字,比如 100、100、100、100 和 500)如果我点击这些数字它应该将我重定向到指定的某个 URL。
    • 谢谢,我们不能让不同的 URL 出现在饼图的每个部分之外吗?目前它只出现在一个地方。
    【解决方案2】:

    您只需要增加弧的outerRadius 即可实现此效果。

    希望这会有所帮助。

     var arcMajorOver = d3.svg.arc()
       .outerRadius(function(d) {
         return radius - 10;
       });
    
     var arcMinorOver = d3.svg.arc()
       .outerRadius(function(d) {
         var s = scale((d.data.major - d.data.minor));
         if (s > radius - 20) {
           return radius - 20;
         }    
         return scale(d.data.major - d.data.minor) + 10;
       });
    
     //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));
       }).on("mouseenter", function(d) {
         d3.select(this)
           .attr("stroke", "white")
           .transition()
           .duration(1000)
           .attr("d", arcMajorOver)
           .style("stroke-width",6);
       })
       .on("mouseleave", function(d) {
         d3.select(this).transition()
           .attr("d", arcMajor)
           .style("stroke-width",0);
       });;;
    
     //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
       }).on("mouseenter", function(d) {
         d3.select(this)
           .attr("stroke", "white")
           .transition()
           .duration(1000)
           .attr("d", arcMinorOver)
           .style("stroke-width",6);
       })
       .on("mouseleave", function(d) {
         d3.select(this).transition()
           .attr("d", arcMinor)
           .style("stroke-width",0);
       });
    

    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 arcMajorOver = d3.svg.arc()
       .outerRadius(function(d) {
         return radius - 10;
       });
    
     //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 arcMinorOver = d3.svg.arc()
       .outerRadius(function(d) {
         var s = scale((d.data.major - d.data.minor));
         if (s > radius - 20) {
           return radius - 20;
         }
    
         return scale(d.data.major - d.data.minor) + 10;
       });
    
     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));
       }).on("mouseenter", function(d) {
         d3.select(this)      
           .transition()
           .duration(1000)
           .attr("d", arcMajorOver)
         .style("stroke-width",6);
       })
       .on("mouseleave", function(d) {
         d3.select(this).transition()
           .attr("d", arcMajor)
           .style("stroke-width", 0);
       });;;
    
     //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
       }).on("mouseenter", function(d) {
         d3.select(this)       
           .transition()
           .duration(1000)
           .attr("d", arcMinorOver)
           .style("stroke-width",6);
       })
       .on("mouseleave", function(d) {
         d3.select(this).transition()
           .attr("d", arcMinor)
           .style("stroke-width", 0);
       });
    .arc text {
      font: 10px sans-serif;
      text-anchor: middle;
    }
    .arc path {
      stroke: #fff;
    }
    &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"&gt;&lt;/script&gt;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-10
      • 1970-01-01
      • 1970-01-01
      • 2014-02-19
      • 1970-01-01
      • 2012-09-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多