veu+D3(v7) 力导向图绘制

代码:

<template>
   <h2><a href="https://d3js.org" target="_blank" >巴黎圣母院人物关系图</a></h2>
    <div id="force-container"></div>
</template>

<script>
import { defineComponent } from 'vue';
//import axios from "axios";
import * as d3 from "d3";
var color=d3.schemeCategory10;

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

export default defineComponent({
    mounted() {      
        this.drawBarChart(nodes,links);      
    },
    methods:{
        drawBarChart(nodes,links){
            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.98;
               const width=800;
                const height=400;
            var svg=d3.select("#force-container")
                        .append("svg")
                        .attr("width",w)
                        .attr("height",h*0.98);
            var forceSimulation = d3.forceSimulation()
                                    .force("link",d3.forceLink())
                                    .force("charge",d3.forceManyBody().strength(-800))
                                    .force("center",d3.forceCenter(w/2,h/2));
            forceSimulation.nodes(nodes)
                           .on("tick");
            forceSimulation.force("link")
                           .links(links)
                           .distance(180);
            var link=svg.selectAll(".link")
                        .data(links)
                        .enter()
                        .append("line")
                        .attr("class","link")
                        .style("stroke-width",1)
                        .style("stroke",(d,i)=>color[i%10])
					    .style("opacity",0.6);
            var node=svg.selectAll(".node")
                        .data(nodes)
                        .enter()
                        .append("circle")
                        .attr("r",16)
                        .style("fill",(d,i)=>color[i%10])
                        .call(drag()); 
            forceSimulation.on("tick",()=>{
                link.attr("x1",d=>d.source.x)
                    .attr("y1",d=>d.source.y)
                    .attr("x2",d=>d.target.x)
                    .attr("y2",d=>d.target.y);
                node.attr("cx",d=>d.x)
                    .attr("cy",d=>d.y);
                edges_text.attr("x",d=>(d.source.x + d.target.x) / 2 )
					.attr("y",d=>(d.source.y + d.target.y) / 2 );
                texts.attr("x",d=>d.x)
					 .attr("y",d=>d.y);
            });
            function drag()
            {
                function dragstarted(event,d){
                    if(!event.active)   forceSimulation.alphaTarget(0.3).restart();
                    d.fx=d.x;
                    d.fy=d.y;
                }
                function dragged(event,d){
                    d.fx=event.x;
                    d.fy=event.y;
                }
                function dragended(event,d){
                    if(!event.active)   forceSimulation.alphaTarget(0);
                    d.fx=null;
                    d.fy=null;
                }
                return d3.drag()
                         .on("start",dragstarted)
                         .on("drag",dragged)
                         .on("end",dragended);
            };
            var edges_text = svg.selectAll(".linetext")
							.data(links)
							.enter()
							.append("text")
							.attr("class","linetext")
							.text(d=> d.relation)
							.style("stroke",(d,i)=>color[i%10])
							.style("font-size",10);	                
            var texts=svg.selectAll(".forceText")
			 .data(nodes)
			 .enter()
			 .append("text")
			 .attr("class","forceText")
			 .style("stroke",(d,i)=>color[i%10])
			 .style("font-size","12px")
			 .attr("text-anchor","middle")
			 .attr("dy",30)
			 .text(d=>d.name);
             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);  
					})
            
        }
    }
})
</script>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值