数据可视化——力导向图的绘制

本次实验数据用的是巴黎圣母院的人物关系图


基于路径绘制力导向图代码如下:

<html>
    <head>
        <meta charset="UTF-8">
        <center><font size="8"><strong>巴黎圣母院人物关系图</strong></font></center>
    </head>
    <body>
        <div style="position: absolute; bottom: 630px; right: 525px;"><font size="2"><strong>数据来源:百度</strong></font></div>
        <script src="d3.v3.min.js"></script>
        <script>           
            var w=window.innerWidth 
            || document.documentElement.clientWidth 
            || document.body.clientWidth;

            var h=window.innerHeight
            || document.documentElement.clientHeight
            || document.body.clientHeight;
            w=w*0.98;
            h=h*0.9;

            var nodes=[{name:"埃斯梅拉达"},{name:"卡西莫多"},{name:"克洛德"},{name:"甘果瓦"},{name:"菲比斯"},{name:"若望"},{name:"小百合"},{name:"居第尔"}];
            
            var edges=[{source:0,target:1,relation:"爱慕"},
            {source:0,target:2,relation:"由爱生恨"},
            {source:0,target:3,relation:"名义夫妻"},
            {source:0,target:4,relation:"爱慕"},
            {source:1,target:2,relation:"养父子"},
            {source:1,target:4,relation:"被逮捕&逮捕"},
            {source:2,target:3,relation:"师生"},
            {source:2,target:4,relation:"情敌"},
            {source:2,target:5,relation:"兄弟"},
            {source:4,target:6,relation:"订婚"},
            {source:0,target:7,relation:"母女"},
            {source:2,target:7,relation:"上下级"}];


            var color=d3.scale.category20();
            var svg=d3.select("body")
                        .append("svg")
                        .attr("width",w)
                        .attr("height",h);
            var force=d3.layout.force()
                        .nodes(nodes)
                        .links(edges)
                        .size([w,h])
                        .linkDistance(300)
                        .charge(-600)
                        .on("tick",tick)
                        .start();
            var path=svg.selectAll("path")
                        .data(edges)
                        .enter()
                        .append("path")
                        .attr("id",function(d,i){return "edgepath"+i;})
                        .attr("stroke","grey");
            var circle=svg.selectAll("circle")
                            .data(nodes)
                            .enter()
                            .append("circle")
                            .attr("r",function(d){
                                if(d.weight<3){
                                    return d.weight*10;
                                }
                                else{
                                    return d.weight*5;
                                }
                            })
                            .attr("fill",function(d,i){
                                return color(i);
                            })
                            .call(force.drag);
            var ntext=svg.selectAll("ntext")
                            .data(nodes)
                            .enter()
                            .append("text")
                            .attr("class",".ntext")
                            .attr("fill","black")
                            .attr("text-anchor","middle")
                            .attr("dy",function(d){
                            if(d.weight<3){
                                    return d.weight*10+12;
                                }
                                else{
                                    return d.weight*5+12;
                                }
                            })
                            .text(function(d){return d.name;})
                            .style("font-size","14px");
            var etext=svg.selectAll("etext")
                            .data(edges)
                            .enter()
                            .append("text")
                            .append("textPath")
                            .attr("xlink:href",function(d,i){return "#edgepath"+i;})
                            .attr("class",".etext")
                            .attr("startOffset","50%")
                            .attr("fill","grey")
                            .attr("text-anchor","middle")
                            .text(function(d){return d.relation;})
                            .style("font-size","14px");
            
            function tick(){
                path.attr("d",function(d){
                    return "M"+d.source.x+","+d.source.y+"L"+d.target.x+","+d.target.y;
                })
                circle.attr("transform",function(d){
                    return "translate("+d.x+","+d.y+")";
                })
                ntext.attr("x",function(d){return d.x;})
                    .attr("y",function(d){return d.y;});
            }
        </script>
    </body>
</html>

基于直线绘制力导向图代码如下:

<html>
    <head>
        <meta charset="UTF-8">
        <center><font size="8"><strong>巴黎圣母院人物关系图</strong></font></center>
        <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: 12px;
				text-align: left;  
				color: black;  
				border-width: 1px solid black;  
				background-color: A9A9A9;  
				border-radius: 3px;  
			}  
			.tooltip:after{   
				content: '';  
				position: absolute;  
				bottom: 100%;  
				left: 20%;  
				margin-left: -3px;  
				width: 0;  
				height: 0;  
				border-bottom: 12px solid rgb(182, 174, 174);  
				border-right: 12px solid transparent;  
				border-left: 12px solid transparent;  
			}  
	</style> 
    </head>
    <body>
        <div style="position: absolute; bottom: 630px; right: 525px;"><font size="2"><strong>数据来源:百度</strong></font></div>
        <script src="d3.v3.min.js"></script>
        <script>           
            var w=window.innerWidth 
            || document.documentElement.clientWidth 
            || document.body.clientWidth;

            var h=window.innerHeight
            || document.documentElement.clientHeight
            || document.body.clientHeight;
            w=w*0.98;
            h=h*0.9;
            
            var nodes=[{name:"埃斯梅拉达",intro:"埃斯梅拉达是雨果笔下集真、善、美于一体的完美的艺术形象。她在小时候被吉普赛人从妓女母亲的呵护下偷走,流浪街头以卖艺为生,虽然饱尝人世的艰辛与苦难,但是却始终保持着一颗善良纯真、乐于助人的心。她是美丽善良的,当乞丐国王要绞死甘果瓦时,她承诺要与甘果瓦结婚救下了他的命;当卡西莫多接受刑法口渴难耐时,只有她站出来以德报怨为他送水。她是勇敢执着的,当克洛德威胁她,只要接受他的爱就能够获得自由时,她斩钉截铁地拒绝了;当菲比斯不顾她的安危死活时,却依然痴心执着的爱着他。"},
            {name:"卡西莫多",intro:"卡西莫多是一个有着几何形的脸,四面体的鼻子,马蹄形的嘴,参差不齐的牙齿,独眼,耳聋,驼背,难听而忠厚的声音的畸形儿。他幼时被父母遗弃在巴黎圣母院门口,后被克洛德收养,成为敲钟人。为报恩,他对克洛德言听计从,绑架了埃斯梅拉达。但在遇到埃斯梅拉达之后,他真诚善良、忠实勇敢的本性被复活了。他奋不顾身地去救处于危险中的埃斯梅拉达,并且不图任何回报。"},
            {name:"克洛德",intro:"克洛德从小接受了良好的宗教教育,是一个勤奋好学、积极向上、知识渊博的青年,他收养丑陋的卡西莫多、照顾年少的弟弟,是有些许善良的。在成为巴黎圣母院的副主教遇到美丽的埃斯梅拉达后,克洛德真实的人性开始表现出来,内心强烈的占有欲迫使他去跟踪、绑架、强抢埃斯梅拉达,这并不是真正意义上的爱情,只是人性中的贪婪和欲望而已。他对埃斯梅拉达的占有欲已经超越了教会思想的束缚,不顾任何人的想法采用极端的做法只能造成悲剧的结局。"},
            {name:"甘果瓦",intro:"流浪诗人,曾因误闯乞丐王国要被绞死,行刑前被埃斯梅拉达以名义婚姻的形式救下。长时间的流浪使他更清楚地认识这个时代和社会,在爱情和物质面前更倾向于选择实际的物质。"},
            {name:"菲比斯",intro:"菲比斯表面上是一个英俊潇洒、美好的皇家卫队队长,深受女孩子的欢迎和喜爱,但是内在却是一个口蜜腹剑、风流成性的伪君子。一方面,菲比斯并不爱他的表妹,却因为表妹的丰厚嫁妆和贵族地位,而同意和表妹结婚,这是一个将金钱、地位摆在第一位的人;另一方面,他虚伪地爱着埃斯梅拉达,因其美丽的外表才一时兴起去追求。单纯的埃斯梅拉达却死心塌地爱上了这个男子,当克洛德因嫉妒袭击菲比斯时,他侥幸逃脱一劫,埃斯梅拉达却冤死在了绞刑架上。"},
            {name:"若望",intro:"巴黎圣母院副主教克洛德之弟,一个游戏人生的小混混,后不满哥哥的所作所为,加入“圣母院”暴动队伍,死于伽西莫多之手。"},
            {name:"小百合",intro:"菲比斯的原未婚妻,最终和甘果瓦成婚。"},
            {name:"居第尔",intro:"埃斯梅拉达的母亲。她在监狱里认出了自己的女儿,在得知分散15年后刚刚找回的骨肉马上就要被吊死了后发狂一样地保护女儿,最后死在女儿的绞架下。"}];
            
            var edges=[{source:0,target:1,relation:"爱慕"},
            {source:0,target:2,relation:"由爱生恨"},
            {source:0,target:3,relation:"名义夫妻"},
            {source:0,target:4,relation:"爱慕"},
            {source:1,target:2,relation:"养父子"},
            {source:1,target:4,relation:"被逮捕&逮捕"},
            {source:2,target:3,relation:"师生"},
            {source:2,target:4,relation:"情敌"},
            {source:2,target:5,relation:"兄弟"},
            {source:4,target:6,relation:"订婚"},
            {source:0,target:7,relation:"母女"},
            {source:2,target:7,relation:"上下级"},
            {source:3,target:6,relation:"夫妻"}];

            var color=d3.scale.category20();
            var force=d3.layout.force()
                        .charge(-600)
                        .linkDistance(300)
                        .size([w,h]);
            var svg=d3.select("body")
                        .append("svg")
                        .attr("width",w)
                        .attr("height",h);
            force.nodes(nodes)
                .links(edges)
                .start();
            var tooltip=d3.selectAll("body")  
                .append("div")  
                .attr("class","tooltip")  
                .style("opacity",0.0); 
            
            var link=svg.selectAll()
                        .data(edges)
                        .enter()
                        .append("line")
                        .attr("class","link")
                        .style("stroke-width",1)
                        .style("stroke","grey")
                        .style("opacity",0.4);
            
            var node=svg.selectAll(".node")
                        .data(nodes)
                        .enter()
                        .append("circle")
                        .attr("class","node")
                        .attr("r",function(d){
                            if(d.weight<3){
                                    return d.weight*10;
                                }
                                else{
                                    return d.weight*5;
                                }
                        })
                        .attr("cx",100)
                        .attr("cy",100)
                        .style("fill",function(d,i){return color(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 text=svg.selectAll(".forcetxt")
                        .data(nodes)
                        .enter()
                        .append("text")
                        .attr("class","forcetxt")
                        .attr("text-anchor","middle")
                        .attr("x",function(d){return d.x;})
                        .attr("y",function(d){return d.y;})
                        .attr("dy",function(d){
                            if(d.weight<3){
                                    return d.weight*10+12;
                                }
                                else{
                                    return d.weight*5+12;
                                }
                        })
                        .text(function(d){return d.name;})
                        .style("font-size","14px");
            var edges_text=svg.selectAll(".linetext")
                                .data(edges)
                                .enter()
                                .append("text")
                                .attr("class","linetext")
                                .attr("fill","grey")  
                                .attr("x",100)
                                .attr("y",200)
                                .text(function(d){return d.relation;})
                                .style("font-size","14px");
                                
            force.on("tick",function(){
                node.attr("cx",function(d){return d.x;})
                    .attr("cy",function(d){return d.y;});

                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;});
                
                text.attr("x",function(d){return d.x;})
                    .attr("y",function(d){return d.y;});
                
                edges_text.attr("x",function(d){ return (d.source.x + d.target.x) / 2 ; })
                            .attr("y",function(d){ return (d.source.y + d.target.y) / 2 ; });

            })
            
        </script>
    </body>
</html>

效果如下:

forcecpath

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值