d3.js實(shí)現(xiàn)簡(jiǎn)單的網(wǎng)絡(luò)拓?fù)鋱D實(shí)例代碼
前言
了解了D3.js的基本開發(fā)和組件以后,我們開始應(yīng)用它激動(dòng)人心之處:絢麗的預(yù)定義圖形,應(yīng)用D3.js,我們?cè)谒氖纠募幕A(chǔ)上稍加變動(dòng)即可應(yīng)用于我們的數(shù)據(jù)可視化工作中,D3.js將后臺(tái)的運(yùn)算已經(jīng)預(yù)定義好,我們只需少量代碼和規(guī)范的數(shù)據(jù),就能做出很花哨(請(qǐng)?jiān)徫业挠迷~不當(dāng))的效果。
力學(xué)圖(也稱為導(dǎo)向圖,也有叫網(wǎng)絡(luò)拓補(bǔ)圖的,反正就是通過(guò)排斥得到關(guān)系遠(yuǎn)近的結(jié)構(gòu))在社交網(wǎng)絡(luò)研究、信息傳播途徑等群體關(guān)系研究中應(yīng)用非常廣泛,它可以直觀地反映群體與群體之間聯(lián)系的渠道、交集多少,群體內(nèi)部成員的聯(lián)系強(qiáng)度等。
本文實(shí)現(xiàn)如下面的效果(用非IE瀏覽器可以看到效果):

代碼有點(diǎn)長(zhǎng),但是也不復(fù)雜,可以參考如下代碼:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.v2.js?2.9.1"></script>
<style type="text/css">
.link { stroke: green; stroke-linejoin:bevel;}
.link_error{
stroke:red;
stroke-linejoin:bevel;
}
.nodetext {
font: 12px sans-serif;
-webkit-user-select:none;
-moze-user-select:none;
stroke-linejoin:bevel;
}
#container{
width:800px;
height:600px;
border:1px solid gray;
border-radius:5px;
position:relative;
margin:20px;
}
</style>
</head>
<body>
<div id='container'></div>
<script type="text/javascript">
function Topology(ele){
typeof(ele)=='string' && (ele=document.getElementById(ele));
var w=ele.clientWidth,
h=ele.clientHeight,
self=this;
this.force = d3.layout.force().gravity(.05).distance(200).charge(-800).size([w, h]);
this.nodes=this.force.nodes();
this.links=this.force.links();
this.clickFn=function(){};
this.vis = d3.select(ele).append("svg:svg")
.attr("width", w).attr("height", h).attr("pointer-events", "all");
this.force.on("tick", function(x) {
self.vis.selectAll("g.node")
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
self.vis.selectAll("line.link")
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
});
}
Topology.prototype.doZoom=function(){
d3.select(this).select('g').attr("transform","translate(" + d3.event.translate + ")"+ " scale(" + d3.event.scale + ")");
}
//增加節(jié)點(diǎn)
Topology.prototype.addNode=function(node){
this.nodes.push(node);
}
Topology.prototype.addNodes=function(nodes){
if (Object.prototype.toString.call(nodes)=='[object Array]' ){
var self=this;
nodes.forEach(function(node){
self.addNode(node);
});
}
}
//增加連線
Topology.prototype.addLink=function(source,target){
this.links.push({source:this.findNode(source),target:this.findNode(target)});
}
//增加多個(gè)連線
Topology.prototype.addLinks=function(links){
if (Object.prototype.toString.call(links)=='[object Array]' ){
var self=this;
links.forEach(function(link){
self.addLink(link['source'],link['target']);
});
}
}
//刪除節(jié)點(diǎn)
Topology.prototype.removeNode=function(id){
var i=0,
n=this.findNode(id),
links=this.links;
while ( i < links.length){
links[i]['source']==n || links[i]['target'] ==n ? links.splice(i,1) : ++i;
}
this.nodes.splice(this.findNodeIndex(id),1);
}
//刪除節(jié)點(diǎn)下的子節(jié)點(diǎn),同時(shí)清除link信息
Topology.prototype.removeChildNodes=function(id){
var node=this.findNode(id),
nodes=this.nodes;
links=this.links,
self=this;
var linksToDelete=[],
childNodes=[];
links.forEach(function(link,index){
link['source']==node
&& linksToDelete.push(index)
&& childNodes.push(link['target']);
});
linksToDelete.reverse().forEach(function(index){
links.splice(index,1);
});
var remove=function(node){
var length=links.length;
for(var i=length-1;i>=0;i--){
if (links[i]['source'] == node ){
var target=links[i]['target'];
links.splice(i,1);
nodes.splice(self.findNodeIndex(node.id),1);
remove(target);
}
}
}
childNodes.forEach(function(node){
remove(node);
});
//清除沒(méi)有連線的節(jié)點(diǎn)
for(var i=nodes.length-1;i>=0;i--){
var haveFoundNode=false;
for(var j=0,l=links.length;j<l;j++){
( links[j]['source']==nodes[i] || links[j]['target']==nodes[i] ) && (haveFoundNode=true)
}
!haveFoundNode && nodes.splice(i,1);
}
}
//查找節(jié)點(diǎn)
Topology.prototype.findNode=function(id){
var nodes=this.nodes;
for (var i in nodes){
if (nodes[i]['id']==id ) return nodes[i];
}
return null;
}
//查找節(jié)點(diǎn)所在索引號(hào)
Topology.prototype.findNodeIndex=function(id){
var nodes=this.nodes;
for (var i in nodes){
if (nodes[i]['id']==id ) return i;
}
return -1;
}
//節(jié)點(diǎn)點(diǎn)擊事件
Topology.prototype.setNodeClickFn=function(callback){
this.clickFn=callback;
}
//更新拓?fù)鋱D狀態(tài)信息
Topology.prototype.update=function(){
var link = this.vis.selectAll("line.link")
.data(this.links, function(d) { return d.source.id + "-" + d.target.id; })
.attr("class", function(d){
return d['source']['status'] && d['target']['status'] ? 'link' :'link link_error';
});
link.enter().insert("svg:line", "g.node")
.attr("class", function(d){
return d['source']['status'] && d['target']['status'] ? 'link' :'link link_error';
});
link.exit().remove();
var node = this.vis.selectAll("g.node")
.data(this.nodes, function(d) { return d.id;});
var nodeEnter = node.enter().append("svg:g")
.attr("class", "node")
.call(this.force.drag);
//增加圖片,可以根據(jù)需要來(lái)修改
var self=this;
nodeEnter.append("svg:image")
.attr("class", "circle")
.attr("xlink:href", function(d){
//根據(jù)類型來(lái)使用圖片
return d.expand ? "http://ww2.sinaimg.cn/large/412e82dbjw1dsbny7igx2j.jpg" : "http://ww4.sinaimg.cn/large/412e82dbjw1dsbnxezrrpj.jpg";
})
.attr("x", "-32px")
.attr("y", "-32px")
.attr("width", "64px")
.attr("height", "64px")
.on('click',function(d){ d.expand && self.clickFn(d);})
nodeEnter.append("svg:text")
.attr("class", "nodetext")
.attr("dx", 15)
.attr("dy", -35)
.text(function(d) { return d.id });
node.exit().remove();
this.force.start();
}
var topology=new Topology('container');
var nodes=[
{id:'10.4.42.1',type:'router',status:1},
{id:'10.4.43.1',type:'switch',status:1,expand:true},
{id:'10.4.44.1',type:'switch',status:1},
{id:'10.4.45.1',type:'switch',status:0}
];
var childNodes=[
{id:'10.4.43.2',type:'switch',status:1},
{id:'10.4.43.3',type:'switch',status:1}
];
var links=[
{source:'10.4.42.1',target:'10.4.43.1'},
{source:'10.4.42.1',target:'10.4.44.1'},
{source:'10.4.42.1',target:'10.4.45.1'}
];
var childLinks=[
{source:'10.4.43.1',target:'10.4.43.2'},
{source:'10.4.43.1',target:'10.4.43.3'},
{source:'10.4.43.2',target:'10.4.43.3'}
]
topology.addNodes(nodes);
topology.addLinks(links);
//可展開節(jié)點(diǎn)的點(diǎn)擊事件
topology.setNodeClickFn(function(node){
if(!node['_expanded']){
expandNode(node.id);
node['_expanded']=true;
}else{
collapseNode(node.id);
node['_expanded']=false;
}
});
topology.update();
function expandNode(id){
topology.addNodes(childNodes);
topology.addLinks(childLinks);
topology.update();
}
function collapseNode(id){
topology.removeChildNodes(id);
topology.update();
}
</script>
</body>
</html>
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以了留言交流。
相關(guān)文章
3分鐘教你用JavaScript實(shí)現(xiàn)電子簽名效果
電子簽名已經(jīng)成為現(xiàn)代商業(yè)中不可或缺的一部分,它可以提高業(yè)務(wù)流程的效率和安全性。本文將介紹如何使用HTML5的canvas元素和JavaScript在前端實(shí)現(xiàn)電子簽名,需要的可以參考一下2023-04-04
性能優(yōu)化篇之Webpack構(gòu)建速度優(yōu)化的建議
這篇文章主要介紹了性能優(yōu)化篇之Webpack構(gòu)建速度優(yōu)化的建議,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
微信小程序云開發(fā)實(shí)現(xiàn)數(shù)據(jù)添加、查詢和分頁(yè)
這篇文章主要為大家詳細(xì)介紹了微信小程序云開發(fā)實(shí)現(xiàn)數(shù)據(jù)添加、查詢和分頁(yè),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-05-05
微信小程序之 catalog 切換實(shí)現(xiàn)解析
這篇文章主要介紹了微信小程序之 catalog 切換實(shí)現(xiàn)解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09
JavaScript實(shí)現(xiàn)帶緩沖效果的隨屏滾動(dòng)漂浮廣告代碼
這篇文章主要介紹了JavaScript實(shí)現(xiàn)帶緩沖效果的隨屏滾動(dòng)漂浮廣告代碼,通過(guò)JavaScript結(jié)合時(shí)間函數(shù)動(dòng)態(tài)響應(yīng)頁(yè)面元素滾動(dòng)事件實(shí)現(xiàn)懸浮廣告的緩沖漂浮效果,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下2015-11-11
JavaScript實(shí)現(xiàn)的原生態(tài)兼容IE6可調(diào)可控滾動(dòng)文字功能詳解
這篇文章主要介紹了JavaScript實(shí)現(xiàn)的原生態(tài)兼容IE6可調(diào)可控滾動(dòng)文字功能,簡(jiǎn)單說(shuō)明了文字滾動(dòng)的實(shí)現(xiàn)原理并結(jié)合具體實(shí)例形式給出了javascript文字滾動(dòng)功能的具體實(shí)現(xiàn)代碼,需要的朋友可以參考下2017-09-09

