实现如下效果:
一、json数据:
{
"data":[
[-0.0282, 0.0545, 0.2327, 0.2276, 0.1717, -0.1646, -0.1646, -0.1646, -0.1646],
[-0.0431, -0.0431, -0.0431, -0.0431, -0.0431, 0.0426, 0.1371, 0.0788, -0.0431],
[-0.0775, -0.2289, -0.2802, -0.2255, 0.2543, -0.0343, -0.0745, 0.196, 0.4706],
[-0.0775, -0.2289, -0.2802, -0.2255, 0.2543, -0.0343, -0.0745, 0.196, 0.4706],
[-0.0775, -0.2289, -0.2802, -0.2255, 0.2543, -0.0343, -0.0745, 0.196, 0.4706],
[-0.0775, -0.2289, -0.2802, -0.2255, 0.2543, -0.0343, -0.0745, 0.196, 0.4706],
[-0.0775, -0.2289, -0.2802, -0.2255, 0.2543, -0.0343, -0.0745, 0.196, 0.4706]
],
"params":{
"title": "这个是热图的标题测试",
"start_color": "#1d953f",
"middle_color": "#130c0e",
"end_color": "#ed1941",
"show_gap":true,
"show_label":true,
"show_column_label": true,
"show_row_label": true,
"rows": ["ENSMUSG00000092137", "ENSMUSG00000090942", "ENSMUSG00000006574", "ENSMUSG00000006573", "ENSMUSG00000006572", "ENSMUSG00000006571", "ENSMUSG00000006570"],
"row_tree": "(ENSMUSG00000006574:0.5283035817,(ENSMUSG00000090942:0.3213435808,ENSMUSG00000092137:0.3213435808):0.2069600009);",
"row_tree_width":50,
"columns": ["C_1fsdds", "B_2weewwrweeewe", "B_1ewewwweweweeweew", "B_3ewrwewewe", "C_3ewerewrwe", "A_3rewreww", "A_1reweew", "A_2ewrweewwwweww", "C_2rewerewwwerwerwee"],
"column_tree": "(((C_1:0.0005501041254,B_2:0.0005501041254):0.01920472318,(B_1:0.001174629219,B_3:0.001174629219):0.01858019809):0.7830263125,(C_3:0.5975157388,((A_3:0.03500377534,A_1:0.03500377534):0.2755466439,(A_2:0.07162426047,C_2:0.07162426047):0.2389261588):0.2869653195):0.205265401);",
"column_tree_height":50,
"row_group":["#FF0000", "#FF0000", "#00FF00", "#00FF00", "#00FF00", "#00FF00", "#00FF00"],
"row_group_width":30,
"row_group_location":"right",
"column_group":["#FF0000", "#FF0000", "#00FF00","#FF0000", "#FF0000", "#00FF00","#FF0000", "#FF0000", "#00FF00"],
"column_group_height":30,
"column_group_location":"bottom",
"row_legend_name":["Taxon_1","Taxon_2","Taxon_3"],
"column_legend_name":["C","N","S"]
},
"size" : {
"width":50,
"height":50
}
}
参数说明:
- 用途:热图(聚类)(不需要指定的属性可以去掉)
- *data,二维数组,一维代表一行
- title:标题
- *start_color[初始颜色],end_color[结束颜色],middle_color[中间过度色,非必填]
- show_gap:是否显示边框,默认false
- show_label:是否显示数值标签,默认false
- show_column_label:是否显示列的标签,默认false
- show_row_label:是否显示行的标签,默认false
- *columns:列的标签名称,一维数组
- *rows:行的标签名称,一维数组
- row_tree:行的聚类树
- row_tree_width:行聚类树的宽度
- column_tree:列的聚类树
- column_tree_width:列聚类树的高度
- row_group:行的分组
- row_group_width:行的分组的宽度
- row_group_location:行的分组的位置,默认left[左],可以调整为right[右]
- column_group:列的分组
- column_group_height:列的分组的高度
- column_group_location:行的分组的位置,默认top[上],可以调整为bottom[下]
- row_legend_name:行的组的图例名称
- column_legend_name:列的组的图例名称
以下为toolip的样式:
<style>
.heatmap_tooltip{
font-family:simsun;
font-size:13px;
width:120;
height:auto;
position:absolute;
text-align:left;
border-style:solid;
border-width:1px;
background-color:white;
border-radius:5px;
}
</style>
二、用到的js插件
#jquery插件
<script src="jquery-1.8.3.min.js"></script>
#d3 v3版本插件
<script src="d3-3.min.js"></script>
#图的实现文件
<script src="heatmap.js"></script>
三、图形的调用
var content = $.parseJSON($('textarea').val()); //从textarea里面取出图的json数据并转化为object
graph.heatmap("container", content); //把生成的图放在#container里面
四、以下为图的代码实现(D3.js实现)
var graph = {
heatmap:function(container, content)
{
var tooltip = d3.select("body").append("div")
.attr("class","heatmap_tooltip")
.attr("opacity",0.0);
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 margin = {
top:100,
left:30,
right:170,
bottom:20,
};
if (typeof(content.params.row_tree_width) != 'undefined' && typeof(content.params.row_tree) != 'undefined') {
margin.left += content.params.row_tree_width;
}
/**分组宽度**/
if (typeof(content.params.row_group) != 'undefined') {
if (typeof(content.params.row_group_location) != 'undefined' && content.params.row_group_location == 'right' && typeof(content.params.row_group_width) != 'undefined'){
margin.right += content.params.row_group_width;
}else if (typeof(content.params.row_group_width) != 'undefined') {
margin.left += content.params.row_group_width;
}
}
if (typeof(content.params.column_tree_height) != 'undefined' && typeof(content.params.column_tree) != 'undefined') {
margin.top += content.params.column_tree_height;
}
/**分组高度**/
if (typeof(content.params.column_group_location) != 'undefined' && content.params.column_group_location == 'bottom' && typeof(content.params.column_group_height) != 'undefined'){
margin.bottom += content.params.column_group_height;
} else if (typeof(content.params.column_group_height) != 'undefined') {
margin.top += content.params.column_group_height;
}
var max_row_lengths = [];
for (var i in content.params.rows) {
max_row_lengths.push(content.params.rows[i].length);
}
var max_column_lengths = [];
for (var i in content.params.columns) {
max_column_lengths.push(content.params.columns[i].length);
}
var row_len = 8;
var column_len = 9;
var max_row_length = d3.max(max_row_lengths);
var max_column_length = d3.max(max_column_lengths);
var heatmap_width = content.size.width * content.params.columns.length;
var heatmap_height = content.size.height * content.params.rows.length;
var width = heatmap_width + margin.left + margin.right;
if (typeof(content.params.row_group_width) != 'undefined') {
width += content.params.row_group_width;
}
if (typeof(content.params.show_row_label) != 'undefined' && content.params.show_row_label === true) {
width += max_row_length * row_len;
}
var height = heatmap_height + margin.top + margin.bottom + max_column_length * column_len;
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 title = typeof(content.params.title) != 'undefined' ? content.params.title : '';
if (title) {
var title_obj = svg.append('text').text(title).attr('y', 25).attr('x', function() {
var text_length = this.getComputedTextLength();
return (margin.left + heatmap_width)/2 - text_length/2;
});
}
/**获取value的最大值、最小值**/
var min_values = [];
var max_values = [];
for (var i in content.data) {
min_values.push(d3.min(content.data[i]));
max_values.push(d3.max(content.data[i]));
}
var min_value = d3.min(min_values);
var max_value = d3.max(max_values);
if (typeof(content.params.middle_color) != 'undefined') {
var color_scale = d3.scale.linear()
.domain([min_value, (min_value+max_value)/2, max_value])
.range([content.params.start_color, content.params.middle_color, content.params.end_color]);
} else {
var color_scale = d3.scale.linear()
.domain([min_value, (min_value+max_value)/2, max_value])
.range([content.params.start_color, content.params.end_color]);
}
console.log(margin.top);
var main = svg.append('g').attr('class', 'main').attr('transform',"translate("+margin.left+", "+margin.top+")");
var xscale = d3.scale.linear()
.domain([0, content.params.columns.length-1])
.range([0, heatmap_width]);
var yscale = d3.scale.linear()
.domain([0, content.params.rows.length -1])
.range([heatmap_height, 0]);
var xaxis = d3.svg.axis()
.scale(xscale)
.ticks(content.params.columns.length -1)
.tickFormat(function(d) {
return content.params.columns[d];
})
.orient('bottom');
var yaxis = d3.svg.axis()
.scale(yscale)
.ticks(content.params.rows.length -1)
.tickFormat(function(d) {
return content.params.rows[d];
})
.orient('right');
var xaxis_y = heatmap_height;
if (typeof(content.params.column_group_location) != 'undefined' && content.params.column_group_location == 'bottom' && typeof(content.params.column_group_height) != 'undefined' && typeof(content.params.column_group) != 'undefined') {
xaxis_y += content.params.column_group_height;
}
var xaxis_obj = main.append('g').attr('class', 'xaxis')
.attr('font-size', 11)
.attr('text-anchor', 'start')
.attr('transform', "translate(0,"+xaxis_y+")")
.call(xaxis);
/**显示、隐藏x标签**/
if (typeof (content.params.show_column_label) != 'undefined' && content.params.show_column_label == true) {
xaxis_obj.selectAll('line').attr('fill', 'none').attr('stroke', '#000');
xaxis_obj.select('.domain').attr('fill', 'none').attr('stroke', '#000');
xaxis_obj.selectAll('.tick').each(function(i) {
var tick_x = content.size.width * i + content.size.width /2;
d3.select(this).attr('transform',"translate("+tick_x+",0)");
});
xaxis_obj.selectAll('.tick').selectAll('text').each(function(d, i) {
d3.select(this).attr('transform', function() {
var html = d3.select(this).html();
d3.select(this).attr('text-anchor', 'start');
return "rotate(110, 8,5) translate("+(this.getComputedTextLength()/2+16)+")";
});
});
} else {
xaxis_obj.attr('opacity', 0);
}
var yaxis_x = heatmap_width;
if (typeof(content.params.row_group_location) != 'undefined' && content.params.row_group_location == 'right' && typeof(content.params.row_group_width) != 'undefined' && typeof(content.params.row_group) != 'undefined') {
yaxis_x += content.params.row_group_width;
}
var yaxis_obj = main.append('g').attr('class', 'yaxis')
.attr('font-size', 11)
.attr('text-anchor', 'bottom')
.attr('transform', "translate("+yaxis_x+",0)")
.call(yaxis);
/**显示、隐藏y标签**/
if (typeof (content.params.show_row_label) != 'undefined' && content.params.show_row_label == true) {
yaxis_obj.selectAll('line').attr('fill', 'none').attr('stroke', '#000');
yaxis_obj.select('.domain').attr('fill', 'none').attr('stroke', '#000');
yaxis_obj.selectAll('.tick').each(function(i) {
var tick_y = content.size.height * i + content.size.height /2;
d3.select(this).attr('transform',"translate(0,"+tick_y+")");
});
} else {
yaxis_obj.attr('opacity', 0);
}
var sub_main = main.append('g').attr('class','sub_main');
sub_main.selectAll('.heatmap_groups').data(content.data).enter()
.append('g').attr('class', function(d, i) {
return "heatmap_groups heatmap_group_"+i;
})
.attr('transform', function(d,i) {
return "translate(0, "+(i*content.size.height)+")";
})
.each(function(d, i) {
var self = d3.select(this);
for (var j in d) {
var rect_g = self.append('g').attr('class', 'h_d_'+i+'_'+j).attr('transform', "translate("+(j*content.size.width)+",0)")
.on('mouseover', function(d) {
var page_x = d3.event.pageX;
var page_y = d3.event.pageY+20;
var self = d3.select(this);
var value = d[self.select('rect').attr('index')];
var point_x = ingredient_legend_scale(value);
legend_pointer.attr('transform', "translate("+point_x+")").attr('fill-opacity', 1);
tooltip.html('<strong>column:</strong>'+content.params.rows[i]+'</br> <strong>row:</strong>'+content.params.columns[j]+'<br /><strong>value:</strong>'+value)
.style("left",page_x+"px")
.style("top",page_y+"px")
.style("opacity",0.9)
.style('padding', '5px');
self.select('rect').attr('fill-opacity', 1);
})
.on('mouseout', function() {
legend_pointer.attr('fill-opacity', 0);
tooltip.style('opacity', 0.0);
var self = d3.select(this);
self.select('rect').attr('fill-opacity', 0.9);
});
var rect = rect_g.append('rect').attr('width', content.size.width).attr('height', content.size.height).attr('fill',color_scale(d[j])).attr('fill-opacity',0.9)
.attr('index', j);
if (typeof(content.params.show_gap) != 'undefined' && content.params.show_gap === true) {
rect.attr('stroke', '#fff');
}
if (typeof(content.params.show_label) != 'undefined' && content.params.show_label == true) {
rect_g.append('text').text(Math.round(d[j]*10000)/10000).attr('x', function () {
return content.size.width /2 - this.getComputedTextLength()/3;
})
.attr('y', function() {
return content.size.height /2+5;
})
.attr('font-size', 11);
}
}
});
/** 绘制行分组**/
if (typeof(content.params.row_group) != 'undefined') {
if (typeof(content.params.row_group_location) != 'undefined' && content.params.row_group_location == 'right' && typeof(content.params.row_group_width) != 'undefined'){
var row_group_x = margin.left + heatmap_width;
} else {
var row_group_x = margin.left - content.params.row_group_width;
}
var row_group = svg.append('g').attr('class', 'row_group').attr('transform', "translate("+row_group_x+","+margin.top+")");
row_group.selectAll('.cat_rows').data(content.params.row_group).enter()
.append('g').attr('class', function(d, i) {
return "cat_rows rows_"+i;
})
.attr('transform', function(d, i) {
return "translate(0, "+(content.size.height)*i+")";
})
.each(function(d, i) {
var self = d3.select(this);
var rect = self.append('rect').attr('width', content.params.row_group_width).attr('height', content.size.height).attr('fill',d).attr('fill-opacity',0.9);
if (typeof(content.params.show_gap) != 'undefined' && content.params.show_gap === true) {
rect.attr('stroke', '#fff');
}
})
}
/** 绘制列分组**/
if (typeof(content.params.column_group) != 'undefined') {
var column_group_x = margin.left;
if (typeof(content.params.column_group_location) != 'undefined' && content.params.column_group_location == 'bottom' && typeof(content.params.column_group_height) != 'undefined'){
var column_group_y = margin.top + heatmap_height;
} else {
var column_group_y = margin.top-content.params.column_group_height;
}
var column_group = svg.append('g').attr('class', 'column_group').attr('transform', "translate("+column_group_x+","+column_group_y+")");
column_group.selectAll('.cat_columns').data(content.params.column_group).enter()
.append('g').attr('class', function(d, i) {
return "cat_columns columns_"+i;
})
.attr('transform', function(d, i) {
return "translate("+(content.size.width*i)+", 0)";
})
.each(function(d, i) {
var self = d3.select(this);
var rect = self.append('rect').attr('width', content.size.width).attr('height', content.params.column_group_height).attr('fill',d).attr('fill-opacity',0.9);
if (typeof(content.params.show_gap) != 'undefined' && content.params.show_gap === true) {
rect.attr('stroke', '#fff');
}
})
}
/**绘制图例**/
function sprintf(text, arr) {
var i = 0;
return text.replace(/\$S/g, function () {
return (i < arr.length) ? arr[i++] : "";
});
}
var color_stops = [
'<stop offset="0%" stop-color="$S"></stop>',
'<stop offset="50%" stop-color="$S"></stop>',
'<stop offset="100%" stop-color="$S"></stop>'
];
if(typeof(content.params.middle_color) == 'undefined'){
color_stops = [color_stops[0], color_stops[2]].join('');
color_stops = sprintf(color_stops, [content.params.start_color, content.params.end_color]);
}else{
color_stops = sprintf(color_stops.join(''), [content.params.start_color, content.params.middle_color, content.params.end_color]);
};
console.log(color_stops);
var defs = svg.append('defs');
/** 定义滤镜颜色**/
defs.append('linearGradient')
.attr({
id: 'ingredient_legend',
x1: "0%",
y1: "0%",
x2: "100%",
y2: "0%"
})
.html(color_stops);
/**定义滤镜上移动的箭头**/
var nonius_scale = 6;
var pointer = "M0 0 " +
"L" + nonius_scale + " " + -nonius_scale + " " +
"L" + nonius_scale + " " + -2 * nonius_scale + " " +
"L" + (-nonius_scale) + " " + -2 * nonius_scale + " " +
"L" + (-nonius_scale) + " " + -nonius_scale + " Z";
var legend_x = width - margin.right;
if (typeof(content.params.row_group_location) != 'undefined' && content.params.row_group_location == 'right' && typeof(content.params.row_group_width) != 'undefined' && typeof(content.params.row_group) != 'undefined') {
legend_x += content.params.row_group_width;
}
var legend = svg.append('g').attr('class', 'legends').attr('transform', 'translate('+legend_x+',30)');
var ingredient_legend = legend.append('g').attr('class', 'ingredient_legend');
var ingredient_legend_width = 150;
var ingredient_legend_height = 20;
ingredient_legend.append('rect').attr('width', ingredient_legend_width).attr('height', ingredient_legend_height).attr('fill', "url(#ingredient_legend)")
.attr('shape-rendering','crispEdges');
var ingredient_legend_scale = d3.scale.linear()
.domain([min_value, max_value])
.range([0, ingredient_legend_width]);
var ingredient_legend_axis = d3.svg.axis()
.scale(ingredient_legend_scale)
.ticks(5)
.orient('bottom');
var ingredient_legend_axis_obj = ingredient_legend.append('g').attr('class', 'legend_axis').attr('transform',"translate(0,"+ingredient_legend_height+")")
.call(ingredient_legend_axis);
ingredient_legend_axis_obj.selectAll('line').attr('fill', 'none').attr('stroke', '#000');
ingredient_legend_axis_obj.select('.domain').attr('fill', 'none').attr('stroke', 'none');
var tick_size = ingredient_legend.select('.legend_axis').selectAll('.tick').size();
ingredient_legend.select('.legend_axis').selectAll('.tick').each(function(d, i) {
if (i != 0 && i != tick_size -1) {
d3.select(this).remove();
}
});
var legend_pointer = ingredient_legend.append("path")
.attr({
class: "legend-pointer",
d: pointer,
fill: "#33a3dc",
"fill-opacity": 0
});
/**绘制行的分组图例**/
var row_legend_y = 70;
if (typeof(content.params.row_legend_name) != 'undefined' && typeof(content.params.row_group) != 'undefined') {
var row_legend = legend.append('g').attr('class', 'row_legend').attr('transform', "translate(0, "+row_legend_y+")").attr('font-size', 11);
row_legend.append('text').text('Taxon group').attr('font-size', 13);
row_legend.selectAll('.child_row_legend').data(content.params.row_legend_name).enter()
.append('g').attr('class', function(d, i) {
return "child_row_legend child_row_"+i;
})
.attr('transform', function(d, i) {
return "translate(0, "+(20+i * 20)+")";
})
.each(function(d, i) {
var self = d3.select(this);
self.append('rect').attr('width', 20).attr('height', 10).attr('fill', content.params.row_group[i]);
self.append('text').text(d).attr('x', 25).attr('y', 8);
});
}
/**绘制列的分组图例**/
if (typeof(content.params.column_legend_name) != 'undefined' && typeof(content.params.column_group) != 'undefined') {
if (typeof(content.params.row_group) != 'undefined' && typeof(content.params.row_legend_name) != 'undefined') {
var column_legend_y = row_legend_y + content.params.row_legend_name.length * 20 + 20 + 30;
} else {
var column_legend_y = row_legend_y;
}
var column_legend = legend.append('g').attr('class', 'column_legend').attr('transform', "translate(0, "+column_legend_y+")").attr('font-size', 11);
column_legend.append('text').text('Sample group').attr('font-size', 13);
column_legend.selectAll('.child_column_legend').data(content.params.column_legend_name).enter()
.append('g').attr('class', function(d, i) {
return "child_column_legend child_column_"+i;
})
.attr('transform', function(d, i) {
return "translate(0, "+(20+i * 20)+")";
})
.each(function(d, i) {
var self = d3.select(this);
self.append('rect').attr('width', 20).attr('height', 10).attr('fill', content.params.column_group[i]);
self.append('text').text(d).attr('x', 25).attr('y', 8);
});
}
/**树**/
var leaf = [];
var max_x = 0;
var getleaf = function(subtree, x) {
if ("undefined" == typeof x) {
x = 0;
}
var sub_y = [];
var length = 0;
if (subtree.length) {
length = subtree.length;
}
subtree.start_x = x;
x = x + length;
subtree.end_x = x;
if (subtree.end_x > max_x) {
max_x = subtree.end_x;
}
if (subtree.branchset) {
for (var i in subtree.branchset) {
sub_y.push(getleaf(subtree.branchset[i], x));
}
} else {
subtree.y = leaf.length;
leaf.push(subtree);
return subtree.y;
}
subtree.y = d3.sum(sub_y) / sub_y.length;
return subtree.y;
};
/**绘制行的树**/
if (typeof(content.params.row_tree) != 'undefined') {
var tree_1 = graph.newickParse(content.params.row_tree);
getleaf(tree_1);
// 定义最左面的树图的宽度的比例尺
var row_ytree_scale = d3.scale.linear().domain([0, leaf.length - 1]).range([margin.top+content.size.height/2, margin.top+heatmap_height-content.size.height/2]);
var row_xtree_scale = d3.scale.linear().domain([0, max_x]).range([5, content.params.row_tree_width - 2]);
var left_x = (margin.left - content.params.row_tree_width);
if (typeof(content.params.row_group_location) != 'undefined' && content.params.row_group_location == 'right' && typeof(content.params.row_group_width) != 'undefined'){
} else if (typeof(content.params.row_group_width) != 'undefined' && typeof(content.params.row_group) != 'undefined') {
left_x -= content.params.row_group_width;
}
var left_tree_obj = svg.append('g').attr('class', 'left_tree').attr('transform', 'translate('+left_x+')');
graph.plotTree(tree_1, left_tree_obj, row_xtree_scale, row_ytree_scale);
}
max_x = 0;
leaf = [];
if (typeof(content.params.column_tree) != 'undefined') {
var tree_1 = graph.newickParse(content.params.column_tree);
getleaf(tree_1);
//定义最上面的树的高度的比例尺
var row_xtree_scale = d3.scale.linear().domain([0, leaf.length - 1]).range([margin.left+content.params.row_tree_width/2,heatmap_width+margin.left-content.params.row_tree_width/2]);
var columny_end = margin.top;
var columny_start = margin.top - content.params.column_tree_height;
if (typeof(content.params.column_group_location) != 'undefined' && content.params.column_group_location == 'bottom' && typeof(content.params.column_group_height) != 'undefined'){
} else if (typeof(content.params.column_group_height) != 'undefined') {
columny_start -= content.params.column_group_height;
columny_end -= content.params.column_group_height;
}
var column_ytree_scale = d3.scale.linear().domain([0, max_x]).range([columny_start, columny_end]);
var top_tree_obj = svg.append('g').attr('class', 'top_tree').attr("transform", "translate(0, 0)");
graph.plotTree(tree_1, top_tree_obj, row_xtree_scale, column_ytree_scale, 'column');
}
},
newickParse:function(string)
{
var ancestors = [];
var tree = {};
var tokens = string.split(/\s*(;|\(|\)|,|:)\s*/);
for (var i = 0; i < tokens.length; i++) {
var token = tokens[i];
switch (token) {
case "(":
var subtree = {};
tree.branchset = [subtree];
ancestors.push(tree);
tree = subtree;
break;
case ",":
var subtree = {};
ancestors[ancestors.length - 1].branchset.push(subtree);
tree = subtree;
break;
case ")":
tree = ancestors.pop();
break;
case ":":
break;
default:
var x = tokens[i - 1];
if (x == ")" || x == "(" || x == ",") {
tree.name = token;
} else if (x == ":") {
tree.length = parseFloat(token);
}
}
}
return tree;
},
plotTree:function(tree, obj,linear_width_scale, linear_height_scale, type) {
if (typeof(type) == 'undefined' || type == 'row') {
graph.plotRow(tree, obj,linear_width_scale, linear_height_scale);
} else {
graph.plotColumn(tree, obj,linear_width_scale, linear_height_scale);
}
if (tree.branchset) {
for (var i in tree.branchset) {
graph.plotTree(tree.branchset[i], obj,linear_width_scale, linear_height_scale, type);
}
}
},
plotRow:function(tree, obj, linear_width_scale, linear_height_scale) {
obj.append("line").attr("x1", linear_width_scale(tree.start_x)).attr("y1", linear_height_scale(tree.y)).attr("x2", linear_width_scale(tree.end_x)).attr("y2", linear_height_scale(tree.y)).attr("stroke-width", 0.8).attr("stroke", '#000');
if (tree.branchset) {
var list_y = [];
for (var i in tree.branchset) {
list_y.push(tree.branchset[i].y);
}
var max_min_y = [d3.min(list_y), d3.max(list_y)];
obj.append("line").attr("x1", linear_width_scale(tree.end_x)).attr("y1", linear_height_scale(max_min_y[1])).attr("x2", linear_width_scale(tree.end_x)).attr("y2", linear_height_scale(max_min_y[0])).attr("stroke-width", 0.8).attr("stroke", '#000');
}
},
plotColumn:function(tree, obj, linear_width_scale, linear_height_scale) {
obj.append("line").attr("x1", linear_width_scale(tree.y)).attr("y1", linear_height_scale(tree.start_x)).attr("x2", linear_width_scale(tree.y)).attr("y2", linear_height_scale(tree.end_x)).attr("stroke-width", 0.8).attr("stroke", '#000');
if (tree.branchset) {
var list_y = [];
for (var i in tree.branchset) {
list_y.push(tree.branchset[i].y);
}
var max_min_y = [d3.min(list_y), d3.max(list_y)];
obj.append("line").attr("x1", linear_width_scale(max_min_y[0])).attr("y1", linear_height_scale(tree.end_x)).attr("x2", linear_width_scale(max_min_y[1])).attr("y2", linear_height_scale(tree.end_x)).attr("stroke-width", 0.8).attr("stroke", '#000');
}
}
};
以上就是图的全部实现,如果有不清楚的地方可以留言,欢迎交流