D3临摹作业(西安交大国家艺术基金数据可视化培训第23天)
程序员文章站
2024-02-13 17:18:46
...
力导向算法
也称为弹簧算法,基于物理系统的引力斥力模型为图上的node和edge布局,用于解决重叠问题。
应用:
绘制过程:
数据(node/edge表示图或网络)-->d3.layout.force()计算节点的位置-->绘制节点(circle/rect)-->绘制边(line/path)
基本原理:
代码:
<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) |
综合案例:
人物社会关系图(代码来源:《数据可视化原理与实例》)
<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
{"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}
]
}
参考文献:
李春芳 石民勇 数据可视化原理与实例 中国传媒大学出版社
推荐阅读
-
《数据可视化原理与实例》临摹作业(西安交大国家艺术基金数据可视化培训第19天)
-
D3临摹作业(西安交大国家艺术基金数据可视化培训第26天)
-
《数据可视化原理与实例》临摹作业(西安交大国家艺术基金数据可视化培训第15天)
-
D3临摹作业(西安交大国家艺术基金数据可视化培训第23天)
-
D3临摹作业(西安交大国家艺术基金数据可视化培训第21天)
-
Spyder临摹作业(西安交大国家艺术基金数据可视化培训第10天)
-
D3临摹作业(西安交大国家艺术基金数据可视化培训第17天)
-
《数据可视化原理与实例》临摹作业(西安交大国家艺术基金数据可视化培训第16天)
-
D3临摹作业(西安交大国家艺术基金数据可视化培训第25天)