D3.js绘制多维饼图

实现如下效果:

多维饼图
一、json数据:
 

{
	"data": [
		[{
			"name": "metabolic process",
			"value": 3532
		}, {
			"name": "cellular process",
			"value": 2814
		}, {
			"name": "single-organism process",
			"value": 2082
		}, {
			"name": "localization",
			"value": 963
		}, {
			"name": "biological regulation",
			"value": 910
		}, {
			"name": "regulation of biological process",
			"value": 817
		}, {
			"name": "cellular component organization or biogenesis",
			"value": 704
		}, {
			"name": "response to stimulus",
			"value": 492
		}, {
			"name": "signaling",
			"value": 192
		}, {
			"name": "negative regulation of biological process",
			"value": 190
		}, {
			"name": "multi-organism process",
			"value": 165
		}, {
			"name": "positive regulation of biological process",
			"value": 163
		}, {
			"name": "reproduction",
			"value": 134
		}, {
			"name": "reproductive process",
			"value": 133
		}, {
			"name": "developmental process",
			"value": 103
		}, {
			"name": "detoxification",
			"value": 34
		}, {
			"name": "growth",
			"value": 27
		}, {
			"name": "multicellular organismal process",
			"value": 20
		}, {
			"name": "biological adhesion",
			"value": 6
		}, {
			"name": "immune system process",
			"value": 2
		}, {
			"name": "locomotion",
			"value": 2
		}, {
			"name": "cell killing",
			"value": 1
		}, {
			"name": "biological phase",
			"value": 1
		}, {
			"name": "cell aggregation",
			"value": 1
		}],
		[{
			"name": "cell",
			"value": 2606
		}, {
			"name": "cell part",
			"value": 2591
		}, {
			"name": "membrane",
			"value": 2195
		}, {
			"name": "organelle",
			"value": 2056
		}, {
			"name": "membrane part",
			"value": 1934
		}, {
			"name": "organelle part",
			"value": 1054
		}, {
			"name": "macromolecular complex",
			"value": 962
		}, {
			"name": "membrane-enclosed lumen",
			"value": 417
		}, {
			"name": "extracellular region",
			"value": 69
		}, {
			"name": "supramolecular complex",
			"value": 31
		}, {
			"name": "virion",
			"value": 23
		}, {
			"name": "virion part",
			"value": 23
		}, {
			"name": "nucleoid",
			"value": 12
		}, {
			"name": "extracellular region part",
			"value": 2
		}],
		[{
			"name": "catalytic activity",
			"value": 3101
		}, {
			"name": "binding",
			"value": 2701
		}, {
			"name": "transporter activity",
			"value": 367
		}, {
			"name": "nucleic acid binding transcription factor activity",
			"value": 193
		}, {
			"name": "structural molecule activity",
			"value": 144
		}, {
			"name": "molecular function regulator",
			"value": 95
		}, {
			"name": "signal transducer activity",
			"value": 37
		}, {
			"name": "transcription factor activity, protein binding",
			"value": 35
		}, {
			"name": "antioxidant activity",
			"value": 32
		}, {
			"name": "electron carrier activity",
			"value": 26
		}, {
			"name": "molecular transducer activity",
			"value": 18
		}, {
			"name": "metallochaperone activity",
			"value": 3
		}, {
			"name": "nutrient reservoir activity",
			"value": 2
		}, {
			"name": "translation regulator activity",
			"value": 2
		}, {
			"name": "protein tag",
			"value": 2
		}]
	],
	"size": {
		"width": 960,
		"height": 900
	},
	"params": {
		"width": 300,
		"title": "GO Classification",
		"sub_title": ["BP", "CC", "MF"],
		"show_label": false
	}
}

二、用到的js插件
#jquery插件

<script src="jquery-1.8.3.min.js"></script>
#d3 v3版本插件

<script src="d3-3.min.js"></script>
#多维饼图的实现文件
<script src="multipie.js"></script>

三、多维饼图的调用
var content = $.parseJSON($('textarea').val()); //从textarea里面取出多维饼图的json数据并转化为object
graph.multiPie("container", content);   //把生成的饼图放在#container里面

四、以下为多维饼图的代码实现(D3.js实现)

/* globals jQuery: true, d3: true */
var graph = {
	multiPie:function(container, content)
	{
		//此处也可以用d3自带的颜色生成器
        var colors = ["#388E3C", "#F44336", "#0288D1", "#FF9800", "#727272", "#E91E63", "#673AB7", "#8BC34A", "#2196F3", "#D32F2F", "#FFC107", "#BDBDBD", "#F8BBD0", "#3F51B5", "#CDDC39", "#009688", "#C2185B", "#FFEB3B", "#212121", "#FFCCBC", "#BBDEFB", "#0099CC", "#FFcc99"];
		
        var pie_width = content.params.width;
        var pie_height = content.params.width;

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

        var lengths = [];

        var group_lengths = [];

        for (var i in content.data) {
            lengths.push(content.data[i].length);
            if (lengths.length == 3) {
                group_lengths.push(d3.max(lengths));
                lengths = [];
            }
        }

        if (lengths.length > 0) {
            group_lengths.push(d3.max(lengths));
            lengths = [];
        }

        console.log(group_lengths);
        
        var width  = pie_width * content.data.length + margin.left+margin.right;

        var height = 0;

        var per_group_y = [0];
        for (var i in group_lengths) {
            var legend_min_height = group_lengths[i] <= 2 ? group_lengths[i] * 7 : 0;
            height += pie_height + group_lengths[i] * 22 + legend_min_height;
            per_group_y.push(height);
        }

        height += margin.top;

        console.log(per_group_y);

		var svg = d3.select('#'+container).append('svg')
            .attr('version', '1.1')
			.attr('style', 'font-family:arial')
			.attr('xmlns', 'http://www.w3.org/2000/svg')
			.attr('width', width)
			.attr('height', height);

        var word_len = 22;
        svg.append('text').text(content.params.title).attr('x', (width - word_len * content.params.title.length)/2).attr('y', 20).attr('font-size', '20px');

        var main_group = svg.append('g').attr('class', 'main_group').attr('transform', "translate("+margin.left+","+margin.top+")");

        var min_size = d3.min([content.params.width, content.params.height]);
		// 得到饼图的比例计算
		var pie = d3.layout.pie()
			.sort(null)
			.value(function(d) {
				return d.value;
			});

        // 计算弧形路径

        // 根据画布大小算一个合适的半径
        var radius = pie_width *0.8/2;

        var arc = d3.svg.arc()
            .innerRadius(5)
            .outerRadius(radius)

        var arc_text = d3.svg.arc()
            .innerRadius(5)
            .outerRadius(radius * 2.2);

        var word_len = 11;
		for (var key in content.data){
            var main_x = parseInt(key) %3 * pie_width;
            var main_y = per_group_y[Math.floor(parseInt(key) / 3)];
            var main = main_group.append('g').attr('class', 'g'+key).attr('transform', "translate("+main_x+", "+(main_y)+")").attr('class', 'main_'+key);

            var sub_obj  = main.append('g').attr('class', 'sub_'+key).attr('transform', "translate(0, 20)");

            main.append('text').text(content.params.sub_title[key]).attr('x', (pie_width - word_len * content.params.sub_title[key].length)/2).attr('y', 15).attr('style', 'font-size:12px');

            var sub_x = (pie_width/2);
            var sub_y = min_size/2;
            var sub_main = sub_obj.append('g').attr('transform', "translate("+sub_x+", "+sub_y+")").attr('class', 'sub_main_'+key);

            var content_data = content.data[key];
            var pie_data = pie(content_data);

            

            //添加弧形

            var pie_path = sub_main.selectAll('g')
                .data(pie_data)
                .enter()
                .append('path')
                .attr('fill', function(d, i) {
                    return colors[i%colors.length];
                })
                .attr('d', function(d) {
                    return arc(d);
                })
                .attr('path', key)
                .attr('class', function(d, i) {
                    return 'path_'+i;
                });

                pie_path.on('mouseover', function(d,i) {
                    var key = d3.select(this).attr('path');
                    d3.select(this).attr('stroke', '#000');
                    if (typeof(content.params.show_label) != 'undefined' && content.params.show_label === false) {
                        d3.select('.main_'+key).select('.sub_main_'+key).select('.sub_text_'+i).attr('opacity', 1.0);
                    }
                    d3.select('.main_'+key).select('.sub_legend_'+key).select('.legend_'+i).select('text').attr('fill', colors[i%colors.length]).attr('style', 'font-weight:bold');
                })
                .on('mouseout', function(d,i) {
                    var key = d3.select(this).attr('path');
                    d3.select(this).attr('stroke', '');
                    if (typeof(content.params.show_label) != 'undefined' && content.params.show_label === false) {
                        d3.select('.main_'+key).select('.sub_main_'+key).select('.sub_text_'+i).attr('opacity', 0.0);
                    }
                    d3.select('.main_'+key).select('.sub_legend_'+key).select('.legend_'+i).select('text').attr('fill', '#000').attr('style', 'font-weight:normal');
                });
                

            var text_obj = sub_main.append('g').attr('class', 'sub_label_'+key);

            var texts = text_obj.selectAll('.texts'+key)
                .data(pie_data)
                .enter()
                .append('text')
                .attr('class', function(d, i) {
                    return 'texts'+key+' '+ 'sub_text_'+i;
                })
                .attr('transform', function(d) {
                    return "translate("+arc_text.centroid(d)+")";
                })
                .attr('text-anchor', function(d) {
                    if ((d.startAngle  +d.endAngle) / 2 < Math.PI) {
                        return "beginning";
                    } else {
                        return "end";
                    }
                })
                .attr('font-size', '10px')
                .text(function(d) {
                    return d.data.value;
                });

                if (typeof(content.params.show_label) != 'undefined' && content.params.show_label === false) {
                    texts.attr('opacity', 0);
                }

            var legend_obj = sub_obj.append('g').attr('transform', 'translate('+(pie_width/5)+','+(pie_width)+')').attr('class', 'sub_legend_'+key);

            legend_obj.selectAll('.legend')
                .data(pie_data)
                .enter()
                .append('g')
                .attr('class', function(d, i) {
                    return "legend legend_"+i;
                })
                .attr('transform', function(d, i) {
                   return "translate(0, "+(i * 20)+")";
                })
                .attr('path', key)
                .each(function(d, i) {
                    var self = d3.select(this);
                    self.append('circle')
                        .attr('cx', 0)
                        .attr('cy', 0)
                        .attr('r', 5)
                        .attr('fill', colors[i%colors.length]);
                    self.append('text')
                        .text(d.data.name)
                        .attr('font-size', '10')
                        .attr('text-anchor', 'start')
                        .attr('transform', "translate(10, 4)")
                        .attr('cursor', 'pointer')
                })
                .on('mouseover', function(d, i) {
                    var self = d3.select(this);
                    var key  = self.attr('path');
                    d3.select('.main_'+key).select('.sub_main_'+key).select('.path_'+i).attr('stroke', '#000');
                    self.select('text').attr('fill', colors[i % colors.length])
                        .attr('style', 'font-weight:bold');

                    if (typeof(content.params.show_label) != 'undefined' && content.params.show_label === false) {
                        d3.select('.main_'+key).select('.sub_main_'+key).select('.sub_text_'+i).attr('opacity', 1);
                    }
                })
                .on('mouseout', function(d, i) {
                    var self = d3.select(this);
                    var key  = self.attr('path');
                    d3.select('.main_'+key).select('.sub_main_'+key).select('.path_'+i).attr('stroke', '');
                    
                    self.select('text').attr('fill', '#000')
                        .attr('style', 'font-weight:normal');

                    if (typeof(content.params.show_label) != 'undefined' && content.params.show_label === false) {
                        d3.select('.main_'+key).select('.sub_main_'+key).select('.sub_text_'+i).attr('opacity', 0.0);
                    }
                });;



        }

	}
};

以上就是多维饼图的全部实现,如果有不清楚的地方可以留言,欢迎交流

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值