实现了根据图的总体宽度来采用横向展示和纵向展示,参数中的width,height属性是每个热图的格子的宽度、高度
实现如下效果:
一、json数据:
{
"data": [
[
[-0.0282, 0.0545, 0.2327, 0.2276, 0.1717, -0.1646, -0.1646, -0.1646],
[-0.0431, -0.0431, -0.0431, -0.0431, -0.0431, 0.0426, 0.1371, 0.0788],
[-0.0775, -0.2289, -0.2802, -0.2255, 0.2543, -0.0343, -0.0745, 0.196],
[-0.0775, -0.2289, -0.2802, -0.2255, 0.2543, -0.0343, -0.0745, 0.196],
[-0.0775, -0.2289, -0.2802, -0.2255, 0.2543, -0.0343, -0.0745, 0.196],
[-0.0775, -0.2289, -0.2802, -0.2255, 0.2543, -0.0343, -0.0745, 0.196],
[-0.0775, -0.2289, -0.2802, -0.2255, 0.2543, -0.0343, -0.0745, 0.196]
],
[
[-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": "这个是热图的标题测试",
"y_label": "Function",
"x_label": "Species",
"start_color": "#1d953f",
"middle_color": "#130c0e",
"end_color": "#ed1941",
"show_gap": true,
"show_label": true,
"orient": "v",
"rows": ["ko0001", "ko0002", "ko0003", "ko0004", "ko0005", "ko0006", "ko0007"],
"columns": [
["MJ1", "MJ2", "MJ3", "MJ4", "MJ5", "MJ6", "MJ7", "MJ8"],
["MJ1", "MJ2", "MJ3", "MJ4", "MJ5", "MJ1e", "MJ7", "MJ8", "MJ9"]
],
"legend": [{
"title": "Proteobacteria",
"desc": "描述1"
}, {
"title": "Actinomycete",
"desc": "描述1"
}, {
"title": "Firmicutes",
"desc": "描述1"
}],
"legend_group_name": "Taxon"
},
"size": {
"width": 50,
"height": 30,
"max_graph_width": 800
}
}
参数说明:
- 用途:热图(物种与功能贡献度分析Heatmap)(不需要指定的属性可以去掉)
- *data,三维数组,按照组的方式进行绘制
- title:标题
- y_label:y轴标签
- x_label:x轴标签
- *start_color[初始颜色],end_color[结束颜色],middle_color[中间过度色,非必填]
- show_gap:是否显示边框,默认false
- show_label:是否显示数值标签,默认false
- *rows:行的标签名称,一维数组
- *columns:列的标签名称,二维数组
- *legend:[title:分组的标题, desc:图例的细节描述]
- legend_group_name:图例分组的title
以下为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="multi_heatmap.js"></script>
三、图形的调用
var content = $.parseJSON($('textarea').val()); //从textarea里面取出图的json数据并转化为object
graph.heatmap("container", content); //把生成的图放在#container里面
四、以下为图的代码实现(D3.js实现)
/* globals jQuery: true, d3: true */
var graph = {
/**渐变图例的比例尺,渐变图例的对象**/
ingredient_legend_scale:null,
legend_pointer:null,
/**每组热图之间的间距**/
heatmap_gap:10,
/**分组的高度**/
group_label_height:30,
/**定义每一个文字的长度**/
per_label_word_len : 6.15,
margin : {
},
tooltip: null,
heatmap:function(container, content)
{
var margin = {
top:50,
left:60,
right:40,
bottom:60,
};
var _margin = {
top:50,
left:60,
right:40,
bottom:60,
};
this.margin = margin;
if (this.tooltip == null){
this.tooltip = d3.select("body").append("div")
.attr("class","heatmap_tooltip")
.attr("opacity",0.0);
}
var column_lengths = new Array();
for (var i in content.params.columns) {
column_lengths.push(content.params.columns[i].length);
}
var rows_lengths = new Array();
for (var i in content.params.rows) {
rows_lengths.push(content.params.rows[i].length);
}
this.margin.left += d3.max(rows_lengths) * this.per_label_word_len;
legend_word_lengths = new Array();
for (var i in content.params.legend) {
legend_word_lengths.push((content.params.legend[i].title+':'+content.params.legend[i].desc).length);
}
margin.right += d3.max(legend_word_lengths) * this.per_label_word_len;
var width = margin.left + content.size.width * d3.sum(column_lengths) + (content.params.columns.length -1) * this.heatmap_gap + margin.right;
var max_graph_width = typeof(content.size.max_graph_width) != 'undefined' ? content.size.max_graph_width : 800;
console.log(_margin);
this.margin = _margin;
console.log(this.margin);
if (width > max_graph_width) {
this.hHeatmap(container, content);
} else {
this.vHeatmap(container, content);
}
return ;
if (typeof(content.params.orient) == 'undefined' || content.params.orient == 'v') {
this.vHeatmap(container, content);
} else {
this.hHeatmap(container, content);
}
},
/**
* 垂直热图
*
**/
vHeatmap:function(container, content)
{
var graph_obj = this;
/**获取列label的长度**/
var column_lengths = new Array();
var group_length = 0;
/**获取每组热图的列的长度**/
var column_length = 0;
var column_group_lengths = new Array();
for (var i in content.params.columns) {
for (var j in content.params.columns[i]) {
column_lengths.push(content.params.columns[i][j].length);
column_length ++;
}
column_group_lengths.push(column_length);
group_length ++;
}
graph_obj.margin.bottom += d3.max(column_lengths) * graph_obj.per_label_word_len;
/**获取行label的长度**/
var rows_lengths = new Array();
for (var i in content.params.rows) {
rows_lengths.push(content.params.rows[i].length);
}
graph_obj.margin.left += d3.max(rows_lengths) * graph_obj.per_label_word_len;
var per_heatmap_height = content.size.height;
var per_heatmap_width = content.size.width;
/**预留图例宽度**/
legend_word_lengths = new Array();
for (var i in content.params.legend) {
legend_word_lengths.push((content.params.legend[i].title+':'+content.params.legend[i].desc).length);
}
graph_obj.margin.right += d3.max(legend_word_lengths) * graph_obj.per_label_word_len;
var width = graph_obj.margin.left + per_heatmap_width * column_lengths.length + (group_length -1) * graph_obj.heatmap_gap + graph_obj.margin.right;
/**绘制区域的热图高度**/
var heatmap_height = per_heatmap_height * content.params.rows.length;
var column_word_len = 0;
var height = graph_obj.margin.top +graph_obj.group_label_height + heatmap_height + graph_obj.margin.bottom;
/**获取value的最大值、最小值,颜色比例尺**/
var min_values = [];
var max_values = [];
for (var i in content.data) {
for (var j in content.data[i]) {
min_values.push(d3.min(content.data[i][j]));
max_values.push(d3.max(content.data[i][j]));
}
}
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]);
}
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 (width - text_length)/2
});
}
var y_label = typeof(content.params.y_label) != 'undefined' ? content.params.y_label : '';
if (y_label) {
svg.append('text').text(y_label).attr('y', function() {
return height /2;
}).attr('transform', function() {
var text_length = this.getComputedTextLength();
return "rotate(-90, 20, "+(height/2)+")";
});
}
var x_label = typeof(content.params.x_label) != 'undefined' ? content.params.x_label : '';
if (x_label) {
svg.append('text').text(x_label).attr('y', function() {
return height - 10;
})
.attr('x', function() {
return (width - this.getComputedTextLength())/2;
})
}
var area = svg.append('g').attr('class', 'area').attr('transform', function() {
return 'translate('+graph_obj.margin.left+ ',' +graph_obj.margin.top+')';
});
var sub_titles = area.append('g').attr('class', 'sub_titles').attr('font-size', 13);
sub_titles.selectAll('.sub_groups').data(content.data).enter()
.append('g').attr('class', function(d, i) {
return 'sub_groups sub_group'+i;
})
.attr('transform', function(d, i) {
var sub_main_x = i > 0 ? column_group_lengths[i-1] * per_heatmap_width + i * graph_obj.heatmap_gap : 0;
return "translate("+sub_main_x+")";
})
.each(function(d, i) {
var self = d3.select(this);
self.append('rect').attr('width', d[0].length * per_heatmap_width).attr('height', graph_obj.group_label_height).attr('fill', '#ccc').attr('stroke', '#555');
self.append('text').text(content.params.legend[i].title).attr('transform', function() {
return "translate("+(d[0].length * per_heatmap_width - this.getComputedTextLength()) /2+", 18)";
})
});
var main = area.append('g').attr('class', 'main').attr('transform',"translate(0, "+graph_obj.group_label_height+")");
main.selectAll('.sub_main').data(content.data).enter()
.append('g').attr('class', function(d, i) {
return 'sub_main sub_main_'+i;
})
.attr('font-size', 11)
.attr('transform', function(d, i) {
var sub_main_x = i > 0 ? column_group_lengths[i-1] * per_heatmap_width + i * graph_obj.heatmap_gap : 0;
return "translate("+sub_main_x+")";
}).each(function(d, i) {
var self = d3.select(this);
self.append('rect').attr('width', content.params.columns[i].length * per_heatmap_width).attr('height', heatmap_height).attr('stroke', '#ccc').attr('fill', 'none');
self.selectAll('.heatmap_groups').data(d).enter()
.append('g').attr('class', function(dd, ii) {
return "heatmap_groups heatmap_groups_"+ii;
})
.attr('transform', function(dd, ii) {
var per_group_y = per_heatmap_height * ii;
return "translate(0,"+per_group_y+")";
})
.each(function(dd, ii) {
var self = d3.select(this);
var hd = self.selectAll('.h_d').data(dd).enter()
.append('g').attr('class', function(ddd, iii) {
return "h_d h_d_"+i+"_"+ii+"_"+iii;
})
.attr('transform', function(ddd, iii) {
var rect_x = per_heatmap_width * iii;
return "translate("+rect_x+")";
})
.each(function(ddd, iii) {
var self = d3.select(this);
var rect = self.append('rect').attr('width', per_heatmap_width).attr('height', per_heatmap_height).attr('stroke-width', 0).attr('stroke', color_scale(ddd)).attr('fill', color_scale(ddd));
if (typeof(content.params.show_gap) != 'undefined' && content.params.show_gap == true){
rect.attr('stroke-width', 1).attr('stroke', '#000');
}
self.append('text').text(Math.round(ddd*10000)/10000).attr('x', function () {
return per_heatmap_width /2 - this.getComputedTextLength()/2;
})
.attr('y', function() {
return per_heatmap_height /2+5;
})
})
.attr('opacity', 0.9)
.on('mouseover', function(ddd, iii) {
var page_x = d3.event.pageX;
var page_y = d3.event.pageY+20;
var self = d3.select(this);
self.attr('opacity', 1);
var point_x = graph_obj.ingredient_legend_scale(ddd);
graph_obj.legend_pointer.attr('transform', "translate("+point_x+")").attr('fill-opacity', 1);
graph_obj.tooltip.html('<strong>column:</strong>'+content.params.rows[ii]+'</br> <strong>row:</strong>'+content.params.columns[i][iii]+'<br /><strong>value:</strong>'+ddd)
.style("left",page_x+"px")
.style("top",page_y+"px")
.style("opacity",0.9)
.style('padding', '5px');
})
.on('mouseout', function() {
graph_obj.legend_pointer.attr('fill-opacity', 0);
var self = d3.select(this);
self.attr('opacity', 0.9);
graph_obj.tooltip.style('opacity', 0.0);
});;
})
/**定一个每一个组的x轴比例尺**/
var xscale = d3.scale.linear()
.domain([0, content.params.columns[i].length-1])
.range([0, per_heatmap_width * d[0].length]);
var xaxis = d3.svg.axis()
.scale(xscale)
.ticks(content.params.columns[i].length)
.tickFormat(function(d) {
return content.params.columns[i][d];
})
.orient('bottom');
var xaxis_y = heatmap_height+4;
var xaxis_obj = self.append('g').attr('class', 'xaxis_'+i)
.attr('font-size', 11)
.attr('text-anchor', 'start')
.attr('transform', "translate(0,"+xaxis_y+")")
.call(xaxis);
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(iiii) {
var tick_x = (iiii) * per_heatmap_width + per_heatmap_width /2;
d3.select(this).attr('transform',"translate("+tick_x+",0)");
d3.select(this).select('text').attr('transform', function() {
d3.select(this).attr('text-anchor', 'start');
return "rotate(90, 8,5) translate("+(this.getComputedTextLength()/2+16)+")";
});
});
})
/**定义y比例尺**/
var yscale = d3.scale.linear()
.domain([0, content.params.rows.length -1])
.range([heatmap_height, 0]);
var yaxis = d3.svg.axis()
.scale(yscale)
.ticks(content.params.rows.length -1)
.tickFormat(function(d) {
return content.params.rows[d];
})
.orient('left');
var yaxis_obj = main.append('g').attr('class', 'yaxis')
.attr('font-size', 11)
.attr('text-anchor', 'bottom')
.call(yaxis);
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 = per_heatmap_height * i + per_heatmap_height /2;
d3.select(this).attr('transform',"translate(0,"+tick_y+")");
});
graph_obj.showLegend(svg, content, {min_value:min_value, max_value:max_value, width:width});
/**------end---------**/
},
/**
* 水平热图
*
**/
hHeatmap:function(container, content)
{
var graph_obj = this;
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"];
/**获取列label的长度**/
var column_lengths = new Array();
var group_length = 0;
/**获取每组热图的列的长度**/
var column_length = 0;
var column_group_lengths = new Array();
for (var i in content.params.columns) {
for (var j in content.params.columns[i]) {
column_lengths.push(content.params.columns[i][j].length);
column_length ++;
}
column_group_lengths.push(column_length);
group_length ++;
}
graph_obj.margin.left += d3.max(column_lengths) * graph_obj.per_label_word_len;
/**获取行label的长度**/
var rows_lengths = new Array();
for (var i in content.params.rows) {
rows_lengths.push(content.params.rows[i].length);
}
graph_obj.margin.bottom += d3.max(rows_lengths) * graph_obj.per_label_word_len;
var per_heatmap_height = content.size.height;
var per_heatmap_width = content.size.width;
/**预留图例宽度**/
legend_word_lengths = new Array();
for (var i in content.params.legend) {
legend_word_lengths.push((content.params.legend[i].title+':'+content.params.legend[i].desc).length);
}
graph_obj.margin.right += d3.max(legend_word_lengths) * graph_obj.per_label_word_len;
var height = graph_obj.margin.top + per_heatmap_height * column_lengths.length + (group_length -1) * graph_obj.heatmap_gap + graph_obj.margin.bottom;
/**绘制区域的热图高度**/
var heatmap_height = per_heatmap_height * content.params.rows.length;
var width = graph_obj.margin.left +graph_obj.group_label_height + per_heatmap_width * content.params.rows.length + graph_obj.margin.right;
/**获取value的最大值、最小值,颜色比例尺**/
var min_values = [];
var max_values = [];
for (var i in content.data) {
for (var j in content.data[i]) {
min_values.push(d3.min(content.data[i][j]));
max_values.push(d3.max(content.data[i][j]));
}
}
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]);
}
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 (width - text_length)/2
});
}
var y_label = typeof(content.params.y_label) != 'undefined' ? content.params.y_label : '';
if (y_label) {
svg.append('text').text(y_label).attr('y', function() {
return height - 10;
})
.attr('x', function() {
return (width - this.getComputedTextLength())/2;
})
}
var x_label = typeof(content.params.x_label) != 'undefined' ? content.params.x_label : '';
if (x_label) {
svg.append('text').text(x_label).attr('y', function() {
return height /2;
}).attr('transform', function() {
var text_length = this.getComputedTextLength();
return "rotate(-90, 20, "+(height/2)+")";
});
}
var area = svg.append('g').attr('class', 'area').attr('transform', function() {
return 'translate('+graph_obj.margin.left+ ',' +graph_obj.margin.top+')';
});
var sub_titles = area.append('g').attr('class', 'sub_titles').attr('font-size', 13);
sub_titles.selectAll('.sub_groups').data(content.data).enter()
.append('g').attr('class', function(d, i) {
return 'sub_groups sub_group'+i;
})
.attr('transform', function(d, i) {
var sub_title_x = content.params.rows.length * per_heatmap_width;
var sub_title_y = i > 0 ? column_group_lengths[i-1] * per_heatmap_height + i * graph_obj.heatmap_gap: 0;
return "translate("+sub_title_x+", "+sub_title_y+")";
})
.each(function(d, i) {
var self = d3.select(this);
self.append('rect').attr('width', graph_obj.group_label_height).attr('height', d[0].length * per_heatmap_height).attr('fill', '#ccc').attr('stroke', '#555');
self.append('text').text(content.params.legend[i].title).attr('transform', function() {
return "translate(0,"+(d[0].length * per_heatmap_height - this.getComputedTextLength()) /2+")rotate(90,5,5)";
})
});
var main = area.append('g').attr('class', 'main');
main.selectAll('.sub_main').data(content.data).enter()
.append('g').attr('class', function(d, i) {
return 'sub_main sub_main_'+i;
})
.attr('font-size', 11)
.attr('transform', function(d, i) {
var sub_main_y = i > 0 ? column_group_lengths[i-1] * per_heatmap_height + i * graph_obj.heatmap_gap : 0;
return "translate(0,"+sub_main_y+")";
})
.each(function(d, i) {
var self = d3.select(this);
self.selectAll('.heatmap_groups').data(d).enter()
.append('g').attr('class', function(dd, ii) {
return "heatmap_groups heatmap_groups_"+ii;
})
.attr('transform', function(dd, ii) {
var per_group_x = per_heatmap_width * ii;
return "translate("+per_group_x+")";
})
.each(function(dd, ii) {
var self = d3.select(this);
var hd = self.selectAll('.h_d').data(dd).enter()
.append('g').attr('class', function(ddd, iii) {
return "h_d h_d_"+i+"_"+ii+"_"+iii;
})
.attr('transform', function(ddd, iii) {
var rect_y = per_heatmap_height * iii;
return "translate(0,"+rect_y+")";
})
.each(function(ddd, iii) {
var self = d3.select(this);
var rect = self.append('rect').attr('width', per_heatmap_width).attr('height', per_heatmap_height).attr('stroke-width', 0).attr('stroke', color_scale(ddd)).attr('fill', color_scale(ddd));
if (typeof(content.params.show_gap) != 'undefined' && content.params.show_gap == true){
rect.attr('stroke-width', 1).attr('stroke', '#000');
}
if (typeof(content.params.show_label) != 'undefined' && content.params.show_label == true) {
self.append('text').text(Math.round(ddd*10000)/10000).attr('x', function () {
return per_heatmap_width /2 - this.getComputedTextLength()/2;
})
.attr('y', function() {
return per_heatmap_height /2+5;
});
}
})
.attr('opacity', 0.9)
.on('mouseover', function(ddd, iii) {
var page_x = d3.event.pageX;
var page_y = d3.event.pageY+20;
var self = d3.select(this);
self.attr('opacity', 1);
var point_x = graph_obj.ingredient_legend_scale(ddd);
graph_obj.legend_pointer.attr('transform', "translate("+point_x+")").attr('fill-opacity', 1);
graph_obj.tooltip.html('<strong>column:</strong>'+content.params.rows[ii]+'</br> <strong>row:</strong>'+content.params.columns[i][iii]+'<br /><strong>value:</strong>'+ddd)
.style("left",page_x+"px")
.style("top",page_y+"px")
.style("opacity",0.9)
.style('padding', '5px');
})
.on('mouseout', function() {
graph_obj.legend_pointer.attr('fill-opacity', 0);
var self = d3.select(this);
self.attr('opacity', 0.9);
graph_obj.tooltip.style('opacity', 0.0);
});
});
var yscale = d3.scale.linear()
.domain([0, content.params.columns[i].length -1])
.range([per_heatmap_height * content.params.columns[i].length, 0]);
var yaxis = d3.svg.axis()
.scale(yscale)
.ticks(content.params.columns[i].length -1)
.tickFormat(function(d) {
return content.params.columns[i][d];
})
.orient('left');
var yaxis_obj = self.append('g').attr('class', 'yaxis')
.attr('font-size', 11)
.attr('text-anchor', 'bottom')
.call(yaxis);
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 = per_heatmap_height * i + per_heatmap_height /2;
d3.select(this).attr('transform',"translate(0,"+tick_y+")");
});
});
/**定义x轴比例尺**/
var xscale = d3.scale.linear()
.domain([0, content.params.rows.length-1])
.range([0, per_heatmap_width * content.params.rows.length]);
var xaxis = d3.svg.axis()
.scale(xscale)
.ticks(content.params.rows.length)
.tickFormat(function(d) {
return content.params.rows[d];
})
.orient('bottom');
var xaxis_y = height - graph_obj.margin.bottom - graph_obj.margin.top+5;
var xaxis_obj = main.append('g').attr('class', 'xaxis_'+i)
.attr('font-size', 11)
.attr('text-anchor', 'start')
.attr('transform', "translate(0,"+xaxis_y+")")
.call(xaxis);
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(iiii) {
var tick_x = (iiii) * per_heatmap_width + per_heatmap_width /2;
d3.select(this).attr('transform',"translate("+tick_x+",0)");
d3.select(this).select('text').attr('transform', function() {
d3.select(this).attr('text-anchor', 'start');
return "rotate(90, 8,5) translate("+(this.getComputedTextLength()/2+16)+")";
});
});
this.showLegend(svg, content, {min_value:min_value, max_value:max_value, width:width});
/**------end---------**/
},
showLegend(svg, content, other)
{
var graph_obj = this;
/**图例**/
var legend_obj = svg.append('g').attr('class', 'legends').attr('transform', 'translate('+(other.width - graph_obj.margin.right + 20)+', '+graph_obj.margin.top+')');
var group_legend = legend_obj.append('g').attr('class','group_legend_title');
group_legend.append('text').text(content.params.legend_group_name).attr('font-size', 12);
group_legend.selectAll('.legend_titles').data(content.params.legend).enter()
.append('g').attr('class', function(d, i) {
return "legend_titles legend_title_"+i;
})
.attr('font-size', 10)
.attr('transform', function(d, i) {
return "translate(0,"+(20 * i + 20)+")";
})
.each(function(d, i) {
var self = d3.select(this);
self.append('text').text(d.title+': '+d.desc);
})
/**渐变图例**/
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]);
};
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 ingredient_legend_width = 60;
var ingredient_legend_height = 17;
var ingredient_legend_y = content.params.legend.length * 20 + 20;
var ingredient_legend = legend_obj.append('g').attr('class', 'ingredient_legend').attr('transform', 'translate(0, '+(ingredient_legend_y)+')');
ingredient_legend.append('rect').attr('width', ingredient_legend_width).attr('height', ingredient_legend_height).attr('fill', "url(#ingredient_legend)")
.attr('shape-rendering','crispEdges');
this.ingredient_legend_scale = d3.scale.linear()
.domain([other.min_value, other.max_value])
.range([0, ingredient_legend_width]);
var ingredient_legend_axis = d3.svg.axis()
.scale(this.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();
}
});
this.legend_pointer = ingredient_legend.append("path")
.attr({
class: "legend-pointer",
d: pointer,
fill: "#33a3dc",
"fill-opacity": 0
});
}
};
以上就是图的全部实现,如果有不清楚的地方可以留言,欢迎交流