参考链接:https://www.cnblogs.com/xcxcxcxc/p/5900444.html
页面:keyword.html
页面代码:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <style> *{ margin: 0; padding: 0; } .main { width: 850px; height: 600px; background-color: #f4f4f4; } #keyword{ width: 100%; height: 100%; } .link { fill: none; stroke: #666; stroke-width: 1.5px; } #licensing { fill: green; } .link.licensing { stroke: green; } .link.resolved { stroke-dasharray: 0,2 1; } circle { fill: #ccc; stroke: #333; stroke-width: 1.5px; } text { font: 12px Microsoft YaHei; pointer-events: none; text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, 0 -1px 0 #fff, -1px 0 0 #fff; } .linetext { font: 12px Microsoft YaHei; } .tooltip{ position: absolute; height: auto; font-family: "microsoft yahei", simhei; font-size: 14px; text-align: center; border: 1px solid #999; padding: 5px; background-color: white; border-radius: 5px; } </style> </head> <body> <div class='main'> <div id="keyword"> </div> </div> <script src="assets/plugins/jquery/jquery-3.3.1.min.js"></script> <script src="assets/plugins/d3/d3.v3.min.js"></script> <script src="assets/js/pages/keyword.js"></script> </body> </html>
keyword.js 代码:
d3.json("assets/data/word.json",function(error,root){ var links = []; for(var i=0;i<root.length;i++){ links.push({ source: root[i].word1, target: root[i].word2, rela: root[i].freq }) } var nodes = {}; links.forEach(function(link) { //利用source和target名称进行连线以及节点的确认 link.source = nodes[link.source] || (nodes[link.source] = {name: link.source}); link.target = nodes[link.target] || (nodes[link.target] = {name: link.target}); }); var width = $("#keyword").width(), height = $("#keyword").height(); var force = d3.layout.force()//layout将json格式转化为力学图可用的格式 .nodes(d3.values(nodes))//设定节点数组 .links(links)//设定连线数组 .size([width, height])//大小 .linkDistance(120)//连接线长度 .charge(-800)//值为+,则相互吸引,绝对值越大吸引力越大。值为-,则相互排斥,绝对值越大排斥力越大 .on("tick", tick)//指时间间隔,隔一段时间刷新一次画面 .start();//开始转换 var zoom = d3.behavior.zoom()//缩放配置, .scaleExtent([0.4, 2])//缩放比例 .on("zoom", zoomed); function zoomed(){//缩放函数 svg.selectAll("g").attr("transform",//svg下的g标签移动大小 "translate(" +d3.event.translate + ")scale(" +d3.event.scale + ")"); /*console.log(d3.event.translate+"/"+d3.event.scale);*/ } var svg = d3.select("#keyword").append("svg")//添加svg元素进行图形的绘制 .attr("width", width) .attr("height", height) .call(zoom); //设置连接线 var edges_line = svg.append("g").selectAll(".edgepath") .data(force.links())//连线数据 .enter() .append("path")//添加path标签 .attr({ 'd': function(d) {return 'M '+d.source.x+' '+d.source.y+' L '+ d.target.x +' '+d.target.y}, 'class':'edgepath',//定义该path标签class为edgepath 'id':function(d,i) {return 'edgepath'+i;}}) .style("stroke","#B43232")//设置线条颜色 .style("stroke-width",0.5)//线条粗细 //连线上的文字 var edges_text = svg.append("g").selectAll(".edgelabel") .data(force.links()) .enter() .append("text")//添加text标签 .attr({ 'class':'edgelabel',//定义该text标签class为edgelabel 'id':function(d,i){return 'edgepath'+i;}, 'dx':50,//在连线上的坐标 'dy':0 }); //设置线条上的文字路径 edges_text.append('textPath') .attr('xlink:href',function(d,i) {return '#edgepath'+i}) .style("pointer-events", "none") .text(function(d){return d.rela;}); function drag(){//拖拽函数 return force.drag() .on("dragstart",function(d){ d3.event.sourceEvent.stopPropagation(); //取消默认事件 d.fixed = true; //拖拽开始后设定被拖拽对象为固定 }); } //圆圈的提示文字 根据需要到数据库中进行读取数据 var tooltip = d3.select("body") .append("div")//添加div并设置成透明 .attr("class","tooltip") .style("opacity",0.0); //圆圈 var circle = svg.append("g") .selectAll("circle") .data(force.nodes())//表示使用force.nodes数据 .enter().append("circle") .style("fill","#39e3db") .style('stroke',"#39e3db") .style('cursor',"pointer") .attr("r",function(node,i){ var r; r = set_r(node.name); return r; })//设置圆圈半径 .on("click",function(node){ //单击时让连接线加粗 edges_line.style("stroke-width",function(line){ if(line.source.name==node.name || line.target.name==node.name){//当与连接点连接时变粗 return 2; }else{ return 0.5; } }); circle.style('stroke-width',1);//所有的圆圈边框 d3.select(this).style('stroke-width',4);//被选中的圆圈边框 }) .on("dblclick",function(d){ //双击节点时节点恢复拖拽 d.fixed = false; }) .on("mouseover",function(d){ set_tooltip(d.name); }) .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(drag());//使顶点可以被拖动 svg.selectAll("g").call(drag());//为svg下的所有g标签添加拖拽事件 svg.on("dblclick.zoom", null);//取消svg和圆圈的双击放大事件(d3中默认开启7个事件,关闭防止与上面的双击事件冲突) circle.on("dblclick.zoom", null); var text = svg.append("g").selectAll("text") .data(force.nodes()) //返回缺失元素的占位对象(placeholder),指向绑定的数据中比选定元素集多出的一部分元素。 .enter() .append("text")//添加text标签 .attr("dy", ".35em") //将文字下移 .attr("text-anchor", "middle")//在圆圈中加上数据 .style('fill',"#555") .style('cursor',"pointer") .on("mouseover",function(d){ set_tooltip(d.name); }) .on("mouseout",function(d){ tooltip.style("opacity",0.0); }) .call(drag()) .attr('x',function(d){ // console.log(d.name+"---"+ d.name.length); var re_en = /[a-zA-Z]+/g; //如果是全英文,不换行 if(d.name.match(re_en)){ d3.select(this).append('tspan')//添加tspan用来方便时使用绝对或相对坐标来调整文本 .attr('x',0) .attr('y',2) .text(function(){return d.name;}); } //如果小于8个字符,不换行 else if(d.name.length<=8){ d3.select(this).append('tspan') .attr('x',0) .attr('y',2) .text(function(){return d.name;}); }else if(d.name.length>=16){//大于16个字符时,将14个字后的内容显示为。。。 var top=d.name.substring(0,8); var bot=d.name.substring(8,14)+"..."; d3.select(this).text(function(){return '';}); d3.select(this).append('tspan')//前n个字 .attr('x',0) .attr('y',-7) .text(function(){return top;}); d3.select(this).append('tspan')//后n个字 .attr('x',0) .attr('y',10) .text(function(){return bot;}); } else {//8-16字符分两行显示 var top=d.name.substring(0,8); var bot=d.name.substring(8,d.name.length); d3.select(this).text(function(){return '';}); d3.select(this).append('tspan') .attr('x',0) .attr('y',-7) .text(function(){return top;}); d3.select(this).append('tspan') .attr('x',0) .attr('y',10) .text(function(){return bot;}); } }); function tick() {//刷新页面函数 circle.attr("transform", transform1);//圆圈 text.attr("transform", transform1);//顶点文字 edges_line.attr('d', function(d) { //连接线 var path='M '+d.source.x+' '+d.source.y+' L '+ d.target.x +' '+d.target.y; return path; }); edges_text.attr('transform',function(d,i){//连线上的文字 if (d.target.x<d.source.x){//判断起点和终点的位置,来让文字一直显示在线的上方且一直是正对用户 bbox = this.getBBox();//获取矩形空间,并且调整翻转中心。(因为svg与css中的翻转不同,具体区别可看http://www.zhangxinxu.com/wordpress/2015/10/understand-svg-transform/) rx = bbox.x+bbox.width/2; ry = bbox.y+bbox.height/2; return 'rotate(180 '+rx+' '+ry+')'; } else { return 'rotate(0)'; } }) .attr('dx',function(d,i){ return Math.sqrt(Math.pow(d.target.x-d.source.x,2)+Math.pow(d.target.y-d.source.y,2))/2-20; //设置文字一直显示在线的中间 }); } //设置圆圈和文字的坐标 function transform1(d) { return "translate(" + d.x + "," + d.y + ")"; } function set_r(name){ //设置圆圈大小 var r; for(var i=0;i<links.length;i++){ if(name == links[i].source.name || name == links[i].target.name){ r=parseInt(links[i].rela) * 3; break; } } return r; } function set_tooltip(name){//设置提示内容 var r; for(var i=0;i<links.length;i++){ if(name == links[i].source.name || name == links[i].target.name){ r=links[i].rela; break; } } tooltip.html(name + "【总次数:" + r + "】") .style("left", (d3.event.pageX) + "px") .style("top", (d3.event.pageY + 20) + "px") .style("opacity",1.0); } })
如果需要初始化图形的大小和位置,可以在js中添加:
zoom.translate([242,180]); zoom.scale(zoom.scale() * 0.4); svg.selectAll("g").attr("transform","translate(242,180)scale(0.4)");
此处的 242,180 和 0.4 可根据实际需要自行修改
如果不想显示连线上文字,可以在js中添加:
edges_text.style("opacity",0);
源码下载:https://pan.baidu.com/s/1j5MS4wT7kSRxHY9nx3Mz2A 密码:9yg6
需要前端资源可前往我的下载主页:https://download.csdn.net/user/qq_34114082/uploads