您的位置:首页 > 其它

D3临摹_力引导算法(西安交大国家艺术基金数据可视化培训第23天)

2019-06-30 02:47 399 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/fox541/article/details/94244522

力导向算法

也称为弹簧算法,基于物理系统的引力斥力模型为图上的node和edge布局,用于解决重叠问题。


应用:

网络层级气泡蜂房、布匹


绘制过程:

数据(node/edge表示图或网络)-->d3.layout.force()计算节点的位置-->绘制节点(circle/rect)-->绘制边(line/path)


基本原理:

代码:

[code]<html>
<head>
<meta charset="utf-8">
<title>一个简单的力引导案例</title>
<style>
.node {
stroke: #fff;
stroke-width: 1.5px;
}
.link {
stroke: #999;
stroke-opacity: .6;
}
</style>
</head>

<body>
<script src="d3.v3.min.js"></script>
<script>
var width=(window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth)*0.98;
var height=(window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight)*0.9;

var color = d3.scale.category20();

var force = d3.layout.force()      //创建为力引导布局
.charge(-120)
.linkDistance(200)
.size([width, height]);

var svg = d3.select("body").append("svg")   //添加svg绘图区
.attr("width", width)
.attr("height", height);
d3.json("a.json", function(error, graph) {
console.log(graph);
force.nodes(graph.nodes)             //绑定图的节点和数据
.links(graph.links)
.start();

var node = svg.selectAll(".node")    //绘制圆形表示节点
.data(graph.nodes)
.enter().append("circle")
.attr("class", "node")
.attr("r", 16)
.style("fill", function(d) { return color(d.group); })
.call(force.drag);

var link = svg.selectAll(".link")       //绘制直线表示边
.data(graph.links)
.enter().append("line")
.attr("class", "link")
.style("stroke-width", function(d) { return Math.sqrt(d.value); });
force.on("tick", function() {
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; });

node.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
});
});

</script>
</body>
</html>

 

节点相关参数:

[D3]

  参数 特点 代码
基本配置参数 d3.layout.force()    
节点相关参数 force.node([nodes])    
force.size([width,height])    
force.friction([])    
force.charge([])    
force.chargeDistance([])    
force.gravity([])    
force.theta([])    
连线相关参数 force.links([])    
force.linkDistance([])    
force.linkStrength([])    
动画相关参数 force.alpha([])    
force.start()    
force.stop()    
force.tick()    
交互相关参数 force.drag() 与call一起使用 node.call(force.drag)


综合案例:

人物社会关系图(代码来源:《数据可视化原理与实例》)

[code]
<html>
<head>
<title>
《人名的名义》人物关系
</title>
<style>
path{
fill: none;
stroke: #666;
stroke-width: 1.5px;
}
circle {
stroke: #333;
stroke-width: 1.5px;
}
text {
font: 10px sans-serif;
pointer-events: none;
}
.tooltip{
position: absolute;
width: 240px;
height: auto;
font-family: simsun;
font-size: 10px;
text-align: left;
color: black;
border-width: 1px solid black;
background-color: 7FFF00;
border-radius: 3px;
}
.tooltip:after{
content: '';
position: absolute;
bottom: 100%;
left: 20%;
margin-left: -3px;
width: 0;
height: 0;
border-bottom: 12px solid black;
border-right: 12px solid transparent;
border-left: 12px solid transparent;
}
</style>
</head>
<body style=" opacity:1">
<script src="d3.v3.min.js" charset="utf-8" ></script>
<script type="text/javascript">
var  width=(window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth)*0.98;
var  height=(window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight)*0.9;
var  img_h=50;
var  img_w=50;
var  radius=10;
var svg=d3.select("body")
.append("svg")
.attr("width",width)
.attr("height",height);
var nodes=[{name:"侯亮平",image:"hlp.jpg",intro:"侯亮平是最高检反贪局侦查处处长,汉东省人民检察院副检察长兼反贪局局长。经过与腐败违法分子的斗争,最终将一批腐败分子送上了审判台,正义战胜邪恶,自己也迎来了成长。"},
{name:"高育良",image:"gyl.jpg",intro:"高育良是汉东省省委副书记兼政法委书记。年近六十,是一个擅长太极功夫的官场老手。侯亮平、陈海和祁同伟都是其学生。"},
{name:"祁同伟",image:"qtw.jpg",intro:"祈同伟是汉东省公安厅厅长。出身农民,曾想凭自己的努力走上去,内心渴望成为一个胜天半子的人,但现实却沉重地打击了他,进而走上了不归路"},
{name:"陈海",image:"ch.jpg",intro:"陈海是汉东省人民检察院反贪局局长。他不畏强权、裁决果断,一出场就与汉东官场权利正面交锋;他廉明正直、重情重义,与好兄弟侯亮平携手战斗在反腐第一线,他遭遇暗害惨出车祸而躺在医院。"},
{name:"蔡成功",image:"ccg.jpg",intro:"蔡成功是汉东省大风厂董事长、法人代表,为人狡诈,为了招标成功而贿赂政府官员,甚至连发小反贪局局长侯亮平也企图想去贿赂。"},
{name:"高小琴",image:"gxq.jpg",intro:"高小琴是山水集团董事长,也是一位叱咤于政界和商界的风云人物,处事圆滑、精明干练。在与官员沟通时更是辩口利辞,沉稳大气,拥有高智商和高情商,并得到以“猴精”著称的反贪局长侯亮平冠以“美女蛇”的称号。"},
{name:"高小凤",image:"gxf.jpg",intro:"高小凤是高小琴的孪生妹妹,高育良的情妇。"},
{name:"陆亦可",image:"lyk.jpg",intro:"陆亦可是汉东省检察院反贪局的女检查官,表面冷峻决绝,内心重情重义。大龄未嫁的她面临着家庭逼婚的困境,而她抗婚是因为对反贪局长陈海一往情深。然而陈海惨遭横祸,她收起悲愤去探求真相拨云见雾,同时在公安局长赵东来的追求中获得真爱。"},
{name:"赵东来",image:"zdl.jpg",intro:"赵东来是汉东省京州市公安局局长。看似直来直去,但却深谋远虑,智勇双全。为了保护正义的尊严,报着坚决整治恶势力的决心,在与检察部门的合作中从最初的质疑到之后的通力配合,展现出现代执法机构的反腐决心。"},
{name:"陈岩石",image:"cys.jpg",intro:"陈岩石是离休干部、汉东省检察院前常务副检察长。充满正义,平凡而普通的共产党人。对大老虎赵立春,以各种形式执着举报了十二年。在这场关系党和国家生死存亡的斗争中,老人家以耄耋高龄,义无反顾"},
{name:"李达康",image:"ldk.jpg",intro:"李达康是汉东省省委常委,京州市市委书记,是一个正义无私的好官。但为人过于爱惜自己的羽毛,对待身边的亲人和朋友显得过于无情"},
{name:"沙瑞金",image:"srj.jpg",intro:"沙瑞金是汉东省省委书记。刚至汉东便发生丁义珍出逃美国事件,又遇到大风厂案。深知汉东政治情况的沙瑞金支持侯亮平查案,要求他上不封顶。"},
{name:"欧阳菁",image:"oyj.jpg",intro:"欧阳菁是汉东省京州市城市银行副行长,京州市市委书记李达康的妻子,后因感情不和离婚。她曾利用职务的便利贪赃枉法。"},
{name:"丁义珍",image:"dyz.jpg",intro:"丁义珍英文名汤姆丁。汉东省京州市副市长兼光明区区委书记。贪污腐败,逃往国外。"},
{name:"季昌明",image:"jcm.jpg",intro:"季昌明是汉东省省级检察院检察长。清廉负责,为人正直,性格温和,但也有些拘泥于教条。对初到汉东省的侯亮平提供了极大地帮助,为破解案件起到了极大地作用。"},
{name:"钟小艾",image:"zxa.jpg",intro:"钟小艾是侯亮平的妻子,中纪委调查组的委派员。"},
{name:"赵瑞龙",image:"zrl.jpg",intro:"赵瑞龙是副国级人物赵立春的公子哥,官二代,打着老子的旗子,黑白两道通吃,权倾一时。把汉东省搅得天翻地覆。"}];
var edges=[{source:0,target:1,relation:"师生"},{source:0,target:2,relation:"同门"},{source:0,target:3,relation:"同学&挚友"},
{source:0,target:4,relation:"发小"},{source:0,target:7,relation:"同事"}, {source:0,target:15,relation:"夫妻"},
{source:14,target:0,relation:"上下级"},{source:1,target:2,relation:"师生"},{source:1,target:3,relation:"师生"},
{source:1,target:6,relation:"情人"}, {source:1,target:11,relation:"上下级"},{source:1,target:10,relation:"政敌"},
{source:2,target:5,relation:"情人"}, {source:2,target:3,relation:"同门&陷害"},  {source:2,target:11,relation:"上下级"},
{source:3,target:9,relation:"父子"},{source:4,target:5,relation:"商业对手"},{source:5,target:6,relation:"孪生姐妹"},
{source:8,target:11,relation:"上下级"},{source:9,target:11,relation:"故交"},
{source:10,target:11,relation:"上下级"},{source:10,target:12,relation:"夫妻"},{source:13,target:10,relation:"上下级"},
{source:12,target:4,relation:"受贿关系"},{source:16,target:2,relation:"利益关系"},{source:16,target:5,relation:"利益关系"}];

var force=d3.layout.force()
.nodes(nodes)
.links(edges)
.size([width,height])
.linkDistance(150)
.charge(-1200)
.start();
//提示框部分
var tooltip=d3.selectAll("body")
.append("div")
.attr("class","tooltip")
.style("opacity",0.0);

//箭头绘制
var defs = svg.append("defs");
var radius=10;
var arrowMarker = defs.append("marker")
.attr("id","arrow")
.attr("markerUnits","strokeWidth")
.attr("markerWidth","4")
.attr("markerHeight","4")
.attr("viewBox","0 0 4 4")
.attr("refX",20+radius/8-2)   //实际是radius/strokeWidth
.attr("refY",2)
.attr("orient","auto");

var arrow_path = "M0,1 L4,2 L0,3 L0,0";

arrowMarker.append("path")
.attr("d",arrow_path);
var color=d3.scale.category20();
var path = svg.selectAll("path")
.data(edges)
.enter()
.append("path")
.attr("id", function(d,i) {
return "edgepath" +i;
})
.attr("class","edges")
.attr("marker-end","url(#arrow)");
var pathtext = svg.selectAll('.pathText')
.data(edges)
.enter()
.append("text")
.attr("class","pathText")
.append('textPath')
.attr("text-anchor", "middle")//居中
.attr("startOffset","50%")
.attr('xlink:href', function(d,i) { return "#edgepath" + i; })
.text(function(d) { return d.relation; });
var  img_h=50;
var  img_w=50;
var  radius=23;
var  circles=svg.selectAll("forceCircle")
.data(nodes)
.enter()
.append("circle")
.attr("class","forceCircle")
.attr("r",radius)
.style("stroke","DarkGray")
.style("stroke-width","1.0px")
.attr("fill", function(d, i){
//创建圆形图片
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+5.8))
.attr("y", - (img_h / 2 - radius+3.5))
.attr("width", img_w+11)
.attr("height", img_h+6)
.attr("xlink:href","image/"+d.image);
return "url(#catpattern" + i + ")";
})
.on("mouseover",function(d,i){    //加入提示框
tooltip.html("角色简介:"+d.intro)
.style("left",(d3.event.pageX)+"px")
.style("top",(d3.event.pageY+20)+"px")
.style("opacity",1.0);
})
.on("mousemove",function(d){
tooltip.style("left",(d3.event.pageX)+"px")
.style("top",(d3.event.pageY+20)+"px"); })
.on("mouseout",function(d){
tooltip.style("opacity",0.0); })
.call(force.drag);
var texts=svg.selectAll(".forceText")
.data(nodes)
.enter()
.append("text")
.attr("class","forceText")
.attr("x",function(d){return d.x;})
.attr("y",function(d){return d.y;})
.style("stroke", "#336666")
.attr("dx","-1.5em")
.attr("dy","3em")
.text(function(d){return d.name;});

force.on("tick",function(){
path.attr("d", function(d) {
var dx = d.target.x - d.source.x;//增量
var dy = d.target.y - d.source.y;
return "M" + d.source.x + ","+ d.source.y + "L" + d.target.x + "," + d.target.y;
});
circles.attr("cx",function(d){return d.x;});
circles.attr("cy",function(d){return d.y;});
texts.attr("x",function(d){return d.x;});
texts.attr("y",function(d){return d.y;});
});
</script>
</body>
</html>

a.json

[code]{"nodes":
[
{"name":"@","group":0},
{"name":"a","group":1},
{"name":"b","group":2}
],
"links":
[
{"source":0,"target":1,"value":1},
{"source":1,"target":2,"value":1},
{"source":2,"target":0,"value":1}
]
}

参考文献:

李春芳 石民勇 数据可视化原理与实例 中国传媒大学出版社

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: