Built with blockbuilder.org
E-mail: cxhair@163.com | Michael Cheng
By pressing left mouse buttom and dragging to select circles you interested, then the chart will be redrawed. You wil like it!
按下鼠标左键并滑动,选择你感兴趣的圆后图形会重绘。你会喜欢的!
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-polyfills/0.1.41/polyfill.min.js"></script>
<script src="https://d3js.org/d3.v3.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
svg{border: 1px solid #ccc;}
#co-expr-chart{width:650px; margin: 10px auto;}
.co-brush .extent{ fill: rgba(85, 178, 212, 0.2); stroke: #000; stroke-width: 1; }
circle.highlight{ fill: red; stroke: black; stroke-width: 2;}
.tooltip{
position: fixed;
border: 2px solid #4b5a7b;
border-radius: 5px;
z-index: 999;
left: -99999px;
background-color: rgba(255,255,255,0.9);
-webkit-box-shadow: 5px 2px 5px 0px rgba(0,0,0,0.5);
box-shadow: 5px 2px 5px 0px rgba(0,0,0,0.5);
}
.tooltip span{
display: block;
margin: 0px;
padding: 2px 4px 4px 4px;
text-align: center;
max-width: 200px;
}
.tooltip span + span{ padding: 0; margin: 2px 5px; }
.tooltip span:first-child{ font-weight: bold; border-bottom: 2px solid #4b5a7b; }
.tooltip span:last-child{ margin-bottom: 0; padding-bottom: 0; }
.tooltip:after{
content: "";
display: block;
position: relative;
margin-right: auto;
margin-left: auto;
width: 0;
height: 0;
top: 10px;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid #4b5a7b;
}
</style>
</head>
<body>
<div id="co-expr-chart"></div>
<div id="tooltip" class="tooltip"></div>
<script>
d3.svg.coEpression = function(id, rData){
var svgWidth = 640,
svgHeight = 640,
margin = {top: 50, right: 40, bottom: 70, left: 80},
width = svgWidth - margin.left - margin.right,
height = svgHeight - margin.top - margin.bottom,
radius = 5,
btuWidth = 50,
btuHeight = 25,
duration = 1000,
color = "#1f77b4";
var tooltip = document.getElementById("tooltip");
if(!tooltip){
tooltip = document.createElement("div");
tooltip.setAttribute("id", "tooltip");
tooltip.setAttribute("class", "tooltip");
document.body.appendChild(tooltip);
}
/*
rData formation:
{
"gene": "RDCA",
"cogene": "ERCC6L",
"data": [
[1.3, 2.5, "TCGA xxx1"],
[2.3, 3.5, "TCGA xxx2"],
[1.8, 1.4, "TCGA xxx3"],
... ...
]
}
*/
var xExtent, yExtent, xScale, yScale, xAxis, yAxis, brush, gene, cogene, pData, pos;
if(!rData){
// alert("Data is EMPTY!"); return;
gene = "RDCA";
cogene = "ERCC6L";
pData = [];
pData = d3.range(1000).map(function(d, i){
return [+(Math.random() * 4 - 2).toFixed(2),
+(Math.random().toFixed(2) * 4 - 2).toFixed(2), "TCGA xxx", i];
});
}else{
gene = rData.gene;
cogene = rData.cogene;
pData = rData.data.map(function(d, i){ d.slice().push(i); });
}
pos = pData[0].length - 1;
function getCircle(){
var ext = brush.extent();
return gCircle.selectAll("circle")
.filter(function(d){
return d[0] >= ext[0][0] && d[0] <= ext[1][0] && d[1] >= ext[0][1] && d[1] <= ext[1][1];
});
}
function onBrushStart(){
//d3.event.preventDefault;
}
function onBrush(){
gCircle.selectAll("circle").classed("highlight", false);
getCircle().classed("highlight", true);
}
function onBrushEnd(){
var selection = getCircle(), sData = [];
selection.classed("highlight", false);
selection.each(function(d){ sData.push(d); });
gBrush.call(brush.clear());
svg.select(".co-show-all").style("display", "block");
if(sData.length >= 1){ reDraw(sData); }
}
function onMouseEnter(d){
var msg = [d[2], gene + " : " + d[0], cogene + " : " + d[1]],
coordinate = d3.mouse(d3.select("html").node());
msg = "<span>" + msg.join("</span><span>") + "</span>";
var box = tooltip.getBoundingClientRect();
d3.select(this).classed("highlight", true);
d3.select(tooltip)
.html(msg)
.style({
display : "block",
left : coordinate[0] - box.width / 2 + "px",
top : coordinate[1] - box.height - 8 + "px"
});
}
function onMouseLeave(){
tooltip.style.left = "-99999px";
d3.select(this).classed("highlight", false);
}
xExtent = d3.extent(pData, function(d){ return d[0]; });
yExtent = d3.extent(pData, function(d){ return d[1]; });
xScale = d3.scale.linear().domain(xExtent).range([0, width]);
yScale = d3.scale.linear().domain(yExtent).range([0, height]);
xAxis = d3.svg.axis().orient("bottom").scale(xScale);
yAxis = d3.svg.axis().orient("left").scale(yScale.copy().range([height, 0]));
brush = d3.svg.brush()
.x(xScale)
.y(yScale.copy().range([height, 0]))
.on("brushstart", onBrushStart)
.on("brush", onBrush)
.on("brushend", onBrushEnd);
var svg = d3.select("#" + id).html("")
.append("svg")
.style("font-size", "12px")
.attr({
width : svgWidth,
height : svgHeight,
version : 1.1,
xmlns : "https://www.w3.org/2000/svg"
});
// useing mask to cover overflowed circles
var coverRect = "<clipPath id='co-coverRect'>" +
"<rect x='0' y='0' width='" + width +"' height='" + height + "' stroke='#333' " + "></rect>" +
"</clipPath>";
svg.append("defs").html(coverRect);
var mainPlot = svg.append("g")
.attr({class: "co-main-plot", transform: "translate(" + [margin.left, margin.top] + ")"}),
gXaxis = mainPlot.append("g")
.attr({
class: "co-axis x-axis",
transform: "translate(" + [0, height + radius * 2] + ")",
"shape-rendering" : "crispEdges"
}),
gYaxis = mainPlot.append("g").attr({
class: "co-axis y-axis",
transform: "translate(" + -radius * 2 + ",0)",
"shape-rendering" : "crispEdges"
}),
gBrush = mainPlot.append("g").attr("class", "co-brush"),
gCircle = mainPlot.append("g").attr({class: "co-circles", "clip-path": "url(#co-coverRect)"});
// insert a background rect
mainPlot.insert("rect", ":first-child")
.attr({
class : "co-background",
width : width,
height : height,
fill : "white",
stroke : "#aaa",
"stroke-width" : 1,
"shape-rendering" : "crispEdges"
});
// axis & uniform
function uniform(s){
s.select(".domain").attr({ fill: "none", stroke: "#aaa", "stroke-width": 1});
s.selectAll(".tick line").attr({ stroke: "#aaa", "stroke-width": 1 });
}
gXaxis.call(xAxis).call(uniform);
gYaxis.call(yAxis).call(uniform);
gBrush.call(brush).call(brush.event);
svg.append("text")
.text("mRNA co-expression: " + gene + " vs " + cogene)
.style("font-size", "16px")
.attr({
transform: "translate(" + [svgWidth * 0.5, 25] + ")",
"text-anchor": "middle", class: "co-main-title"
});
svg.append("text")
.text(cogene + " mRNA expression")
.attr({
transform: "translate(" + [20, margin.top + 0.5 * height] + ")rotate(-90)",
"text-anchor": "middle", class: "co-y-title"
});
svg.append("text")
.text(gene + " mRNA expression")
.attr({
transform: "translate(" + [margin.left + 0.5 * width, svgHeight - 15] + ")",
"text-anchor": "middle", class: "co-x-title"
});
svg.append("g")
.attr({
class:"co-show-all",
transform: "translate(" + [svgWidth - btuWidth - 10, svgHeight - btuHeight - 10] + ")"
})
.style({display: "none", cursor: "pointer"})
.call(function(s){
s.append("text")
.text("Restore")
.attr({ x: 0.5 * btuWidth, y: 0.5 * btuHeight, "text-anchor": "middle", dy: 3 });
s.append("rect")
.attr({ width: btuWidth, height: btuHeight, fill: "transparent", stroke: "#333", "stroke-width": 1 })
.on("click", function(){ reDraw(pData); d3.select(this.parentNode).style("display", "none"); });
});
function reDraw(data){
xExtent = d3.extent(data, function(d){ return d[0]; })
.map(function(d, i){ return i ? 0.1 + d : d - 0.1; }); // spare a little space
yExtent = d3.extent(data, function(d){ return d[1]; })
.map(function(d, i){ return i ? 0.1 + d : d - 0.1; }); // spare a little space
xScale.domain(xExtent);
yScale.domain(yExtent);
yAxis.scale(yScale.copy().range([height, 0]));
gXaxis.transition().call(xAxis).call(uniform);
gYaxis.transition().call(yAxis).call(uniform);
brush.y(yScale.copy().domain(yExtent.slice().reverse()));
var updata = gCircle.selectAll("circle")
.data(data, function(d){return d[pos];});
updata
.enter()
.append("circle")
.attr({
cx : 0.5 * width,
cy : 0.5 * height,
r : 0,
fill : color
})
.on("mouseenter", onMouseEnter)
.on("mouseleave", onMouseLeave);
updata
.transition()
.duration(duration)
.attr({
cx : function(d){ return xScale(d[0]); },
cy : function(d){ return height - yScale(d[1]); },
r : radius
});
updata.exit()
.transition()
.duration(duration / 2)
.attr({r: 0})
.remove();
}
reDraw(pData);
}; // coEpression END
d3.svg.coEpression("co-expr-chart");
d3.select(self.frameElement).style({width: 750 + "px",height: 750 + "px"});
</script>
</body>
https://cdnjs.cloudflare.com/ajax/libs/js-polyfills/0.1.41/polyfill.min.js
https://d3js.org/d3.v3.min.js