d3.jså ³ç³»å¾
<!DOCTYPE html>
<html>
<head>
<style>
.nodetext {
font-size: 12px;
font-family: SimSun;
fill: #000000;
}
.tooltip {
height: auto;
font-family: simsun;
font-size: 14px;
text-align: center;
}
select#lineFontType.form-control,
select#nodesFontType.form-control {
width: 184px;
}
.layout-split-east {
border-left: 5px solid #E6EEF8;
}
</style>
<base href="<%=basePath%>">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://code.jquery.com/jquery-3.0.0.min.js"></script>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
</head>
<body>
<!-- å导åå¾div -->
<div id="divid"></div>
<script>
$(document).ready(function () {
showChart();
})
function showChart() {
var data = {
"links": [
{ "source": "éæ´", "target": "建é¶å½é
产ä¸åºé管çæéå
¬å¸", "relation": "å¯è£äºé¿å¤§äºº", "sourceId": "", "targetId": "", "sourceImg": "http://mail.tom.com/error/i2.gif", "targetImg": "", "sourceColor": "", "targetColor": "", "sourceRadius": "30", "targetRadius": "45", "lineColor": "#458B00" },
{ "source": "汪红è¾", "target": "ä¹¾è¡æåæèµå
¬å¸", "relation": "æ»ç»ç", "sourceId": "", "targetId": "", "sourceImg": "", "targetImg": "", "sourceColor": "", "targetColor": "#00FF00", "sourceRadius": "30", "targetRadius": "40", "lineColor": "#EEEE00" },
{ "source": "汪红è¾", "target": "天津è£ä¸°è¡ææèµç®¡çæéå
¬å¸", "relation": "è£äº", "sourceId": "", "targetId": "", "sourceImg": "", "targetImg": "", "sourceColor": "", "targetColor": "", "sourceRadius": "30", "targetRadius": "42", "lineColor": "#0000CD" },
{ "source": "汪红è¾", "target": "ä¹¾è¡æåæèµå
¬å¸", "relation": "æ³äºº", "sourceId": "", "targetId": "", "sourceImg": "", "targetImg": "", "sourceColor": "", "targetColor": "", "sourceRadius": "30", "targetRadius": "40", "lineColor": "#9AC0CD" },
{ "source": "汪红è¾", "target": "ä¹¾è¡æåæèµå
¬å¸", "relation": "è£äºé¿", "sourceId": "", "targetId": "", "sourceImg": "", "targetImg": "", "sourceColor": "", "targetColor": "", "sourceRadius": "30", "targetRadius": "40", "lineColor": "#CD4F39" },
{ "source": "汪红è¾", "target": "建é¶å½é
产ä¸åºé管çæéå
¬å¸", "relation": "è£äº", "sourceId": "", "targetId": "", "sourceImg": "", "targetImg": "", "sourceColor": "", "targetColor": "", "sourceRadius": "30", "targetRadius": "45", "lineColor": "#0000CD" },
{ "source": "è¡ç« å®", "target": "建é¶å½é
产ä¸åºé管çæéå
¬å¸", "relation": "è£äºé¿", "sourceId": "", "targetId": "", "sourceImg": "", "targetImg": "", "sourceColor": "", "targetColor": "", "sourceRadius": "30", "targetRadius": "45", "lineColor": "#CD4F39" },
{ "source": "建é¶å½é
产ä¸åºé管çæéå
¬å¸", "target": "è¡ç« å®", "relation": "æ³äºº", "sourceId": "", "targetId": "", "sourceImg": "", "targetImg": "", "sourceColor": "", "targetColor": "", "sourceRadius": "45", "targetRadius": "30", "lineColor": "#9AC0CD" }
]
};
var options = {};
options.backgroundColor = "#D1EEEE";
options.nodesFontType = "SimSun";
options.nodesFontSize = 20;
options.lineFontType = "SimHei";
options.lineFontSize = 12;
options.lineColor = "#000000";
options.showExamples = true;
options.examplesX = 20;
options.examplesY = 450;
options.examplesFontColor = "#000000";
drawChart("divid", options, data);
}
function drawChart(divid, options, datas, dataFilter) {
var backgroundColor = options.backgroundColor; //èæ¯é¢è²
var nodesFontType = options.nodesFontType; //èç¹åä½
var nodesFontSize = options.nodesFontSize; //èç¹åå·
var lineFontType = options.lineFontType; //å
³ç³»åä½
var lineFontSize = options.lineFontSize; //å
³ç³»åå·
var lineColor = options.lineColor; //è¿çº¿é¢è²
var examplesFontColor = options.examplesFontColor; //å
³ç³»ç¤ºä¾åä½é¢è²
var width = 800; //ç»å¸å®½
var height = 500; //ç»å¸é«
var svgChart = d3.select("svg");
svgChart.remove();
var tip = $(".tooltip");
if (tip.length > 0) {
tip.remove();
}
var sourceDatas = {};
sourceDatas.links = [];
for (var i = 0; i < datas.links.length; i++) {
var jsonObj = {};
jsonObj.source = datas.links[i].source;
jsonObj.target = datas.links[i].target;
jsonObj.relation = datas.links[i].relation;
jsonObj.sourceId = datas.links[i].sourceId;
jsonObj.targetId = datas.links[i].targetId;
jsonObj.sourceImg = datas.links[i].sourceImg;
jsonObj.targetImg = datas.links[i].targetImg;
jsonObj.sourceColor = datas.links[i].sourceColor;
jsonObj.targetColor = datas.links[i].targetColor;
jsonObj.sourceRadius = datas.links[i].sourceRadius;
jsonObj.targetRadius = datas.links[i].targetRadius;
jsonObj.lineColor = datas.links[i].lineColor;
sourceDatas.links.push(jsonObj);
}
var resourceLinks = sourceDatas.links;
if (dataFilter != undefined && dataFilter.length > 0) {
var indexArray = [];
for (var i = 0; i < dataFilter.length; i++) {
for (var j = 0; j < resourceLinks.length; j++) {
if (resourceLinks[j].relation == dataFilter[i].relation && dataFilter[i].isShow == "false") {
indexArray.push(j);
}
}
}
if (indexArray.length > 0) {
var tempArray = [];
for (var j = 0; j < resourceLinks.length; j++) {
for (var i = 0; i < indexArray.length; i++) {
if (indexArray[i] != j) {
if (i == indexArray.length - 1) {
tempArray.push(resourceLinks[j]);
break;
}
continue;
} else {
break;
}
}
}
resourceLinks = tempArray;
}
}
var links = resourceLinks;
//å
³ç³»åç»
var linkGroup = {};
//对è¿æ¥çº¿è¿è¡ç»è®¡ååç»ï¼ä¸åºåè¿æ¥çº¿çæ¹åï¼åªè¦å±äºå两个å®ä½ï¼å³è®¤ä¸ºæ¯åä¸ç»
var linkmap = {};
for (var i = 0; i < links.length; i++) {
var key = links[i].source < links[i].target ? links[i].source + ':' + links[i].target : links[i].target + ':' + links[i].source;
if (!linkmap.hasOwnProperty(key)) {
linkmap[key] = 0;
}
linkmap[key] += 1;
if (!linkGroup.hasOwnProperty(key)) {
linkGroup[key] = [];
}
linkGroup[key].push(links[i]);
}
//为æ¯ä¸æ¡è¿æ¥çº¿åé
sizeå±æ§ï¼åæ¶å¯¹æ¯ä¸ç»è¿æ¥çº¿è¿è¡ç¼å·
for (var i = 0; i < links.length; i++) {
var key = links[i].source < links[i].target ? links[i].source + ':' + links[i].target : links[i].target + ':' + links[i].source;
links[i].size = linkmap[key];
//åä¸ç»çå
³ç³»è¿è¡ç¼å·
var group = linkGroup[key];
//ç»èç¹åé
ç¼å·
setLinkNumber(group);
}
//èç¹
var nodes = {};
//å
³ç³»å¯¹åºé¢è²
var relationColor = {};
for (var i = 0; i < links.length; i++) {
links[i].source = nodes[links[i].source] || (nodes[links[i].source] = { name: links[i].source, color: links[i].sourceColor, image: links[i].sourceImg, radius: links[i].sourceRadius });
links[i].target = nodes[links[i].target] || (nodes[links[i].target] = { name: links[i].target, color: links[i].targetColor, image: links[i].targetImg, radius: links[i].targetRadius });
}
var sourceData = datas.links;
for (var i = 0; i < sourceData.length; i++) {
relationColor[sourceData[i].relation] = { "relation": sourceData[i].relation, "lineColor": sourceData[i].lineColor };
}
nodes = d3.values(nodes);
relationColor = d3.values(relationColor);
var examples_x = parseFloat(options.examplesX); //å
³ç³»ç¤ºä¾åæ x
var examples_y = parseFloat(options.examplesY); //å
³ç³»ç¤ºä¾åæ y
var examplesLength = 80;
var examplesSize = Math.floor((width - examples_x) / examplesLength);
var examplesRow = relationColor.length % examplesSize == 0 ? relationColor.length / examplesSize : Math.ceil(relationColor.length / examplesSize);
//计ç®å
³ç³»ç¤ºåä½ç½®
for (var i = 1; i <= relationColor.length; i++) {
var num = i % examplesSize == 0 ? examplesSize : i % examplesSize;
relationColor[i - 1].x = examples_x + (num - 1) * examplesLength;
relationColor[i - 1].y = examples_y + 20 * Math.ceil(i / examplesSize);
}
if (dataFilter == undefined) {
dataFilter = [];
for (var i = 0; i < relationColor.length; i++) {
dataFilter.push({ "relation": relationColor[i].relation, "isShow": "true" });
}
}
//ç»å®ç¸è¿èç¹
for (var i = 0; i < nodes.length; i++) {
for (var j = 0; j < links.length; j++) {
if (nodes[i].name == links[j].source.name) {
nodes[i][links[j].target.name] = { name: links[j].target.name };
}
if (nodes[i].name == links[j].target.name) {
nodes[i][links[j].source.name] = { name: links[j].source.name };
}
}
}
var svg = d3.select("#" + divid).append("svg")
.attr("width", width)
.attr("height", height)
.attr("style", "background-color:" + backgroundColor);
if (options.showExamples == "true") {
var examples = svg.selectAll(".examples")
.data(relationColor)
.enter()
.append("svg:g")
.attr("fill-opacity", function (d) {
for (var i = 0; i < dataFilter.length; i++) {
if (d.relation == dataFilter[i].relation && dataFilter[i].isShow == "false") {
return 0.2;
}
}
return 1;
})
.on("click", function (d) {
for (var i = 0; i < dataFilter.length; i++) {
if (dataFilter[i].relation == d.relation) {
if (dataFilter[i].isShow == "true") {
dataFilter[i].isShow = "false";
} else {
dataFilter[i].isShow = "true";
}
}
}
drawChart(divid, options, datas, dataFilter);
});
examples.append("svg:path")
.attr("d", function (d) {
var x1 = d.x;
var y1 = d.y;
var x2 = x1 + 20;
var y2 = y1;
return 'M' + x1 + ' ' + y1 + ' L ' + x2 + ' ' + y2;
})
.style("stroke", function (d) {
if (d.lineColor == "") {
return lineColor;
} else {
return d.lineColor;
}
})
.style("stroke-width", 2.5);
examples.append("svg:text")
.style("font-size", "14px")
.style("fill", examplesFontColor)
.attr("x", function (d) {
if (d.relation.length > 3) {
return d.x + 20 + 14 * 4 / 2;
}
return d.x + 20 + 14 * d.relation.length / 2;
})
.attr("y", function (d) {
return d.y + 5;
})
.attr('text-anchor', "middle")
.text(function (d) {
if (d.relation.length > 3) {
return d.relation.substring(0, 3) + "...";
}
return d.relation;
})
.on("mouseover", function (d) {
tooltip.html("<span>" + d.relation + "</span>")
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY + 20) + "px")
.style("display", "block")
.style("position", "absolute")
.style("opacity", 1.0);
})
.on("mouseout", function (d, i) {
tooltip.style("opacity", 0.0);
});
}
//D3å导åå¸å±
var force = d3.layout.force()
.nodes(nodes)
.links(links)
.size([width, height])
.linkDistance(200)
.charge(-1500)
.start();
//è¾¹
var edges_path = svg.selectAll(".edgepath")
.data(links)
.enter()
.append("path")
.attr("marker-end", function (d, i) {
var arrowMarker = svg.append("marker")
.attr("id", "arrow" + i)
.attr("markerUnits", "userSpaceOnUse")
.attr("markerWidth", "16")
.attr("markerHeight", "15")
.attr("viewBox", "0 0 12 12")
.attr("refX", 9)
.attr("refY", 6)
.attr("orient", "auto")
.append("svg:path")
.attr("d", "M2,2 L10,6 L2,10 L6,6 L2,2")
.attr("fill", function () {
return d.lineColor = "" ? lineColor : d.lineColor;
});
return "url(#arrow" + i + ")";
})
.style("stroke", function (d) {
if (d.lineColor == "") {
return lineColor;
} else {
return d.lineColor;
}
})
.style("stroke-width", 1.5)
.on("mouseover", function (d) {
//å½±èå
¶å®è¿çº¿ä¸æå
edges_text.style("fill-opacity", function (edge) {
if (edge === d) {
return 1;
}
return 0;
})
edges_path.style("stroke-width", function (edge) {
if (edge === d) {
return 4;
}
return 1.5;
})
})
.on("mouseout", function (d, i) {
//æ¾ç¤ºè¿çº¿ä¸çæå
edges_text.style("fill-opacity", 1);
edges_path.style("stroke-width", 1.5);
});
//è¾¹ä¸çæåï¼äººç©ä¹é´çå
³ç³»ï¼
var edges_text = svg.selectAll(".linetext")
.data(links)
.enter()
.append("svg:g")
.attr("class", "linetext")
.attr("fill-opacity", 1);
edges_text.append("svg:text")
.style("font-size", (lineFontSize + "px"))
.style("font-family", lineFontType)
.style("fill", "#000000")
.attr("y", ".31em")
.attr('text-anchor', "middle")
.text(function (d) {
return d.relation;
});
edges_text.insert('rect', 'text')
.attr('width', function (d) {
return d.relation.length * lineFontSize;
})
.attr('height', function (d) {
return lineFontSize;
})
.attr("y", "-.6em")
.attr('x', function (d) {
return -d.relation.length * lineFontSize / 2;
})
.style('fill', '#fff');
// åå½¢å¾çèç¹ï¼äººç©å¤´åï¼
var circle = svg.selectAll("circle")
.data(nodes)
.enter()
.append("circle")
.style("stroke", function (d) {
if (d.color == "") {
return "#EE8262";
}
return d.color;
})
.style("stroke-width", "2px")
.attr("r", function (d) {
return d.radius;
})
.attr("fill", function (d, i) {
//èç¹å¾çä¸ä¸ºç©ºæ¯æ·»å èæ¯è²
if (d.image == "") {
if (d.color == "") {
return "#EE8262";
}
return d.color;
} else {
//å建åå½¢å¾ç
var defs = svg.append("defs").attr("id", "imgdefs")
var catpattern = defs.append("pattern")
.attr("id", "catpattern" + i)
.attr("height", 1)
.attr("width", 1)
catpattern.append("image")
/* .attr("x", - (img_w / 2 - radius))
.attr("y", - (img_h / 2 - radius)) */
.attr("width", d.radius * 2)
.attr("height", d.radius * 2)
.attr("xlink:href", d.image)
return "url(#catpattern" + i + ")";
}
})
.on("mouseover", function (d, i) {
//å½±èå
¶å®è¿çº¿ä¸æå
edges_text.style("fill-opacity", function (edge) {
if (edge.source === d || edge.target === d) {
return 1;
}
if (edge.source !== d && edge.target !== d) {
return 0;
}
})
//å
¶å®èç¹äº®åº¦è°ä½
circle.style("opacity", function (edge) {
var v = d.name;
if (edge.name == v || (edge[v] != undefined && edge[v].name == v)) {
return 1;
} else {
return 0.2;
}
})
//å
¶ä»è¿å
亮度è°ä½
edges_path.style("opacity", function (edge) {
if (edge.source === d || edge.target === d) {
return 1;
}
if (edge.source !== d && edge.target !== d) {
return 0.2;
}
})
//å
¶ä»èç¹æå亮度è°ä½
nodes_text.style("opacity", function (edge) {
var v = d.name;
if (edge.name == v || (edge[v] != undefined && edge[v].name == v)) {
return 1;
} else {
return 0.2;
}
})
})
.on("mouseout", function (d, i) {
//æ¾ç¤ºè¿çº¿ä¸çæå
edges_text.style("fill-opacity", 1);
edges_path.style("opacity", 1);
circle.style("opacity", 1);
nodes_text.style("opacity", 1);
tooltip.style("opacity", 0.0);
})
.call(force.drag);
var tooltip = d3.select("body").append("div")
.attr("class", "tooltip")
.attr("opacity", 0.0);
var nodes_text = svg.selectAll(".nodetext")
.data(nodes)
.enter()
.append("text")
.style("font-size", (nodesFontSize + "px"))
.style("font-family", nodesFontType)
.attr('x', function (d) {
var name = d.name;
//å¦æå°äºå个å符ï¼ä¸æ¢è¡
if (name.length < 4) {
d3.select(this).append('tspan')
.attr("dx", -nodesFontSize * (name.length / 2))
.text(function () { return name; });
} else if (name.length >= 4 && name.length <= 6) {
var top = d.name.substring(0, 3);
var bot = d.name.substring(3, name.length);
d3.select(this).append('tspan')
.attr("dx", -nodesFontSize * 1.5)
.attr("dy", -nodesFontSize * 0.5)
.text(function () { return top; });
d3.select(this).append('tspan')
.attr("dx", -(nodesFontSize * name.length / 2))
.attr("dy", nodesFontSize)
.text(function () { return bot; });
} else if (name.length > 7) {
var top = d.name.substring(0, 3);
var mid = d.name.substring(3, 6);
var bot = d.name.substring(6, name.length);
d3.select(this).append('tspan')
.attr("dx", -nodesFontSize * 1.5)
.attr("dy", -nodesFontSize * 0.5)
.text(function () { return top; });
d3.select(this).append('tspan')
.attr("dx", -nodesFontSize * 3)
.attr("dy", nodesFontSize)
.text(function () { return mid; });
d3.select(this).append('tspan')
.attr("dx", -nodesFontSize * 2)
.attr("dy", nodesFontSize)
.text(function () { return "..."; });
}
})
.on("mouseover", function (d, i) {
//å½±èå
¶å®è¿çº¿ä¸æå
edges_text.style("fill-opacity", function (edge) {
if (edge.source === d || edge.target === d) {
return 1;
}
if (edge.source !== d && edge.target !== d) {
return 0;
}
})
//å
¶ä»èç¹äº®åº¦è°ä½
circle.style("opacity", function (edge) {
var v = d.name;
if (edge.name == v || (edge[v] != undefined && edge[v].name == v)) {
return 1;
} else {
return 0.2;
}
})
//å
¶ä»è¿çº¿äº®åº¦è°ä½
edges_path.style("opacity", function (edge) {
if (edge.source === d || edge.target === d) {
return 1;
}
if (edge.source !== d && edge.target !== d) {
return 0.2;
}
})
//å
¶ä»èç¹æå亮度è°ä½
nodes_text.style("opacity", function (edge) {
var v = d.name;
if (edge.name == v || (edge[v] != undefined && edge[v].name == v)) {
return 1;
} else {
return 0.2;
}
})
tooltip.html("<span>" + d.name + "</span>")
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY + 20) + "px")
.style("display", "block")
.style("opacity", 1.0);
})
.on("mouseout", function (d, i) {
//æ¾ç¤ºè¿çº¿ä¸çæå
edges_text.style("fill-opacity", 1);
edges_path.style("opacity", 1);
circle.style("opacity", 1);
nodes_text.style("opacity", 1);
tooltip.style("opacity", 0.0);
})
.call(force.drag);
var drag = force.drag()
.on("dragstart", function (d, i) {
d.fixed = true; //ææ½å¼å§å设å®è¢«ææ½å¯¹è±¡ä¸ºåºå®
})
.on("dragend", function (d, i) {
})
.on("drag", function (d, i) {
});
//åå¦å¾è¿å¨å¼å§æ¶
force.on("start", function () {
});
//åå¦å¾è¿å¨ç»ææ¶
force.on("end", function () {
});
force.on("tick", function () {
//éå¶ç»ç¹çè¾¹ç
nodes.forEach(function (d, i) {
d.x = d.x - 45 < 0 ? 45 : d.x;
d.x = d.x + 45 > width ? width - 45 : d.x;
d.y = d.y - 45 < 0 ? 45 : d.y;
d.y = d.y + 45 > height ? height - 45 : d.y;
});
edges_path.attr("d", function (d) {
var tan = Math.abs((d.target.y - d.source.y) / (d.target.x - d.source.x)); //åå¿è¿çº¿tanå¼
var x1 = d.target.x - d.source.x > 0 ? Math.sqrt(d.sourceRadius * d.sourceRadius / (tan * tan + 1)) + d.source.x :
d.source.x - Math.sqrt(d.sourceRadius * d.sourceRadius / (tan * tan + 1)); //èµ·ç¹xåæ
var y1 = d.target.y - d.source.y > 0 ? Math.sqrt(d.sourceRadius * d.sourceRadius * tan * tan / (tan * tan + 1)) + d.source.y :
d.source.y - Math.sqrt(d.sourceRadius * d.sourceRadius * tan * tan / (tan * tan + 1)); //èµ·ç¹yåæ
var x2 = d.target.x - d.source.x > 0 ? d.target.x - Math.sqrt(d.targetRadius * d.targetRadius / (1 + tan * tan)) :
d.target.x + Math.sqrt(d.targetRadius * d.targetRadius / (1 + tan * tan));//ç»ç¹xåæ
var y2 = d.target.y - d.source.y > 0 ? d.target.y - Math.sqrt(d.targetRadius * d.targetRadius * tan * tan / (1 + tan * tan)) :
d.target.y + Math.sqrt(d.targetRadius * d.targetRadius * tan * tan / (1 + tan * tan));//ç»ç¹yåæ
if (d.target.x - d.source.x == 0 || tan == 0) { //æçæ 穷大çæ
åµæ为0æ¶
y1 = d.target.y - d.source.y > 0 ? d.source.y + d.sourceRadius : d.source.y - d.sourceRadius;
y2 = d.target.y - d.source.y > 0 ? d.target.y - d.targetRadius : d.target.y + d.targetRadius;
}
if (d.linknum == 0) {//设置ç¼å·ä¸º0çè¿æ¥çº¿ä¸ºç´çº¿ï¼å
¶ä»è¿æ¥çº¿ä¼ååå¨ä¸¤è¾¹
d.x_start = x1;
d.y_start = y1;
d.x_end = x2;
d.y_end = y2;
return 'M' + x1 + ' ' + y1 + ' L ' + x2 + ' ' + y2;
}
var a = d.sourceRadius > d.targetRadius ? d.targetRadius * d.linknum / 3 : d.sourceRadius * d.linknum / 3;
var xm = d.target.x - d.source.x > 0 ? d.source.x + Math.sqrt((d.sourceRadius * d.sourceRadius - a * a) / (1 + tan * tan)) :
d.source.x - Math.sqrt((d.sourceRadius * d.sourceRadius - a * a) / (1 + tan * tan));
var ym = d.target.y - d.source.y > 0 ? d.source.y + Math.sqrt((d.sourceRadius * d.sourceRadius - a * a) * tan * tan / (1 + tan * tan)) :
d.source.y - Math.sqrt((d.sourceRadius * d.sourceRadius - a * a) * tan * tan / (1 + tan * tan));
var xn = d.target.x - d.source.x > 0 ? d.target.x - Math.sqrt((d.targetRadius * d.targetRadius - a * a) / (1 + tan * tan)) :
d.target.x + Math.sqrt((d.targetRadius * d.targetRadius - a * a) / (1 + tan * tan));
var yn = d.target.y - d.source.y > 0 ? d.target.y - Math.sqrt((d.targetRadius * d.targetRadius - a * a) * tan * tan / (1 + tan * tan)) :
d.target.y + Math.sqrt((d.targetRadius * d.targetRadius - a * a) * tan * tan / (1 + tan * tan));
if (d.target.x - d.source.x == 0 || tan == 0) {//æçæ 穷大æ为0æ¶
ym = d.target.y - d.source.y > 0 ? d.source.y + Math.sqrt(d.sourceRadius * d.sourceRadius - a * a) : d.source.y - Math.sqrt(d.sourceRadius * d.sourceRadius - a * a);
yn = d.target.y - d.source.y > 0 ? d.target.y - Math.sqrt(d.targetRadius * d.targetRadius - a * a) : d.target.y + Math.sqrt(d.targetRadius * d.targetRadius - a * a);
}
var k = (x1 - x2) / (y2 - y1);//è¿çº¿å线çæç
var dx = Math.sqrt(a * a / (1 + k * k)); //ç¸å¯¹åç¹xè½´è·ç¦»
var dy = Math.sqrt(a * a * k * k / (1 + k * k)); //ç¸å¯¹åç¹yè½´è·ç¦»
if ((y2 - y1) == 0) {
dx = 0;
dy = Math.sqrt(a * a);
}
if (a > 0) {
var xs = k > 0 ? xm - dx : xm + dx;
var ys = ym - dy;
var xt = k > 0 ? xn - dx : xn + dx;
var yt = yn - dy;
} else {
var xs = k > 0 ? xm + dx : xm - dx;
var ys = ym + dy;
var xt = k > 0 ? xn + dx : xn - dx;
var yt = yn + dy;
}
//è®°å½è¿çº¿èµ·å§åç»æ¢åæ ï¼ç¨äºå®ä½çº¿ä¸æå
d.x_start = xs;
d.y_start = ys;
d.x_end = xt;
d.y_end = yt;
return 'M' + xs + ' ' + ys + ' L ' + xt + ' ' + yt;
});
//æ´æ°è¿æ¥çº¿ä¸æåçä½ç½®
edges_text.attr("transform", function (d) {
return "translate(" + (d.x_start + d.x_end) / 2 + "," + (d.y_start + d.y_end) / 2 + ")" + " rotate(" + Math.atan((d.y_end - d.y_start) / (d.x_end - d.x_start)) * 180 / Math.PI + ")";
});
//æ´æ°ç»ç¹å¾çåæå
circle.attr("cx", function (d) { return d.x });
circle.attr("cy", function (d) { return d.y });
nodes_text.attr("x", function (d) { return d.x });
nodes_text.attr("y", function (d) { return d.y });
});
}
function setLinkNumber(group) {
if (group.length == 0) return;
if (group.length == 1) {
group[0].linknum = 0;
return;
}
var maxLinkNumber = group.length % 2 == 0 ? group.length / 2 : (group.length - 1) / 2;
if (group.length % 2 == 0) {
var startLinkNum = -maxLinkNumber + 0.5;
for (var i = 0; i < group.length; i++) {
group[i].linknum = startLinkNum++;
}
} else {
var startLinkNum = -maxLinkNumber;
for (var i = 0; i < group.length; i++) {
group[i].linknum = startLinkNum++;
}
}
}
</script>
</html>
gitå°åï¼https://github.com/binliuli/visual.git