java+数据库+D3.js 实时查询人物关系图

时间:2020-12-06 00:49:03

先看下 效果

java+数据库+D3.js 实时查询人物关系图

某个用户,邀请了自己的朋友 ,自己的朋友邀请了其他朋友,1 展示邀请关系,2 点击头像显示邀请人和被邀请人的关系。(网上这种资料很少, 另外很多都是从JSON文件取 数据, 这里是从数据库取数据)

=================================================================================================需求:Java从数据库查用户表,管理平台可以实时查看每个月用户的邀请关系图。

以下是代码:

1.Java 方法

    1.1 controller 根据某个手机号码查出JSON

 

    /**
*
@param model
*
@param mobile
*
@return
*/
@RequestMapping(value
= "/relation")
public ModelAndView toRelation(Model model,@RequestParam("mobile")String mobile) {
String userName
= AuthUtils.getAuthenticationObject().getName();
Customer user
=userService.getUserByname(userName);
model.addAttribute(
"role", user.getRole());
model.addAttribute(
"username", user.getMobile());
JSONObject json
= customerService.findUserRelation(mobile);
model.addAttribute(
"json", json);

System.out.println(json);
return new ModelAndView("relation");
}

 

1.2 service 方法(递归查询,JSON处理)

    /**
* 根据手机号码查询人物关系图
*
@param mobile
*
@return
*/
public JSONObject findUserRelation(String mobile) {
JSONObject json
= new JSONObject();
// 首先查询当前用户
Customer customer = userService.getUserByname(mobile);
List
<RelationBo> list = new ArrayList<RelationBo>();
// 根节点,只看子类
// 递归获取当前用户的所有子类。
list = getAllRelation(new ArrayList<RelationBo>(), customer.getUid());
list.add(
0, new RelationBo(mobile,Constants.TOP_USER,
customer.getUid(),
null));
// 获取用户信息JSONArray
JSONArray peopleArray = new JSONArray();
JSONArray targetArray
= new JSONArray();
SourceTargetBo bo
= null;
JSONObject peoJ
= null;

List
<String> photoList= RelationUtil.getRandomPhoto();
for (int i = 0; i < list.size(); i++) {
peoJ
=new JSONObject();
peoJ.put(
"name", list.get(i).getName());
// peoJ.put("image", list.get(i).getImage());
peoJ.put("image", photoList.get(i));
peopleArray.add(peoJ);
for (int j = 0; j < list.size(); j++) {
if(list.get(j).getPuid()==null||list.get(j).getPuid()==list.get(i).getUid()){
continue;
}
if (list.get(i).getUid().equals(list.get(j).getPuid())) {
bo
= new SourceTargetBo(i, j,"resolved",RelationUtil.getRelation());
// 找到子类序号
targetArray.add(bo);

}
}

}
// 人物JSON
json.put("nodes", peopleArray);
// 关系JSON
json.put("edges", targetArray);
return json;
}

private List<RelationBo> getAllRelation(List<RelationBo> bo, String uid) {
// 查询这个用户下的所有子用户
List<Customer> list = customerDao.findAllChild(uid);
RelationBo relation
= null;
if (list == null || list.size() == 0) {
// 当前用户没有子用户了!
return bo;
}
else {
for (Customer cus : list) {
relation
= new RelationBo(cus.getMobile(), Constants.BOOTOM_USER,
cus.getUid(), cus.getPuid());
// 所有子用户添加到树中
bo.add(relation);
// 递归查询子用户的所有子用户
bo = getAllRelation(bo, cus.getUid());

}

}
return bo;
}

 

1.3 mybatis

<select id="findAllChild" resultType="com.ycmedia.entity.Customer">
select
* from r_user where puid=#{uid}
</select>

1.4 数据库 因为数据库暂时没有用户头像,所以随机工具类定义了几个头像

java+数据库+D3.js 实时查询人物关系图

1.5 工具类, 获得随机关系, 用户头像

package com.ycmedia.utils;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class RelationUtil {


public static String getRelation(){

List
<String> list = new ArrayList<String>();
list.add(
"");
list.add(
"亲人");
list.add(
"同学");
list.add(
"朋友");
list.add(
"同事");
list.add(
"邻居");
int Num=new Random().nextInt(4)+1;
return list.get(Num);

}


public static List<String> getRandomPhoto(){

List
<String> list = new ArrayList<String>();
list.add(
"http://apps.ycmedia.cn/qm/img/31f96dc747eb4e4383ab7f990afc9775.jpg");
list.add(
"http://appdemo.b0.upaiyun.com/qm/img/lable/60x60/1480730644618.jpg");
list.add(
"http://appdemo.b0.upaiyun.com/qm/img/lable/60x60/1480730825975.jpg");
list.add(
"http://appdemo.b0.upaiyun.com/qm/img/lable/60x60/1480730901129.jpg");
list.add(
"http://appdemo.b0.upaiyun.com/qm/img/lable/60x60/1480730947894.jpg");
return list;
}



}

  1.7 最后的JSON格式

java+数据库+D3.js 实时查询人物关系图

 

 

 

=========================以上是Java, 下面是    html

 

 2.1 html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>邀请关系图</title>
<style>
.nodetext
{
font-size
: 12px ;
font-family
: SimSun;
fill
:#000000;
}

.linetext
{
font-size
: 12px ;
font-family
: SimSun;
fill
:#0000FF;
fill-opacity
:0.0;
}
path.link
{
fill
: none;
stroke
: #666;
stroke-width
: 1.5px;
}

marker#licensing
{
fill
: green;
}

path.link.licensing
{
stroke
: green;
}

path.link.resolved
{
stroke
: green;
}

circle
{
fill
: #ccc;
stroke
: #333;
stroke-width
: 1.5px;
}

text
{
font
: 10px sans-serif;
pointer-events
: none;
}

text.shadow
{
stroke
: #fff;
stroke-width
: 3px;
stroke-opacity
: .8;
}
</style>
</head>
<body>
<input type="hidden" th:value="${json}" id="json" />
<script src="/bootstrap/jQuery/jquery-2.2.3.min.js"></script>
<script src="/js/d3.v3.min.js" charset="utf-8"></script>
<script>
var obj=$("#json").val();
var root = JSON.parse(obj);

var width = 1200;
var height = 1200;
var img_w = 77;
var img_h = 90;

var svg = d3.select("body").append("svg:svg")
.attr(
"width", width)
.attr(
"height", height);



var force = d3.layout.force()
.nodes(root.nodes)
.links(root.edges)
.size([width,height])
.linkDistance(
200)
.charge(
-1500)
.start();

//控制线条
var edges_line = svg.selectAll("line")
.data(root.edges)
.enter()
.append(
"line")
.style(
"stroke","#ccc")
.style(
"stroke-width",1);
//控制文字
var edges_text = svg.selectAll(".linetext")
.data(root.edges)
.enter()
.append(
"text")
.attr(
"class","linetext")
.text(
function(d){
return d.relation;
});


var path = svg.append("svg:g").selectAll("path")
.data(force.links())
.enter().append(
"svg:path")
.attr(
"class", function(d) { return "link " + d.type; })
.attr(
"marker-end", function(d) { return "url(#" + d.type + ")"; });

//控制图片
var nodes_img = svg.selectAll("image")
.data(root.nodes)
.enter()
.append(
"image")
.attr(
"width",img_w)
.attr(
"height",img_h)
.attr(
"xlink:href",function(d){
return d.image;
})
.on(
"mouseover",function(d,i){
edges_text.style(
"fill-opacity",function(edge){
if( edge.source === d || edge.target === d ){
return 1.0;
}
});
})
.on(
"mouseout",function(d,i){
edges_text.style(
"fill-opacity",function(edge){
if( edge.source === d || edge.target === d ){
return 0.0;
}
});
})
.call(force.drag);

var text_dx = -20;
var text_dy = 20;

var nodes_text = svg.selectAll(".nodetext")
.data(root.nodes)
.enter()
.append(
"text")
.attr(
"class","nodetext")
.attr(
"dx",text_dx)
.attr(
"dy",text_dy)
.text(
function(d){
return d.name;
});


force.on(
"tick", function(){

edges_text.attr(
"x",function(d){ return (d.source.x + d.target.x) / 2 ; });
edges_text.attr(
"y",function(d){ return (d.source.y + d.target.y) / 2 ; });


nodes_img.attr(
"x",function(d){ return d.x - img_w/2; });
nodes_img.attr("y",function(d){ return d.y - img_h/2; });

nodes_text.attr(
"x",function(d){ return d.x });
nodes_text.attr(
"y",function(d){ return d.y + img_w/2; });

path.attr(
"d", function(d) {
var dx = d.target.x - d.source.x,//增量
dy = d.target.y - d.source.y,
dr
= Math.sqrt(dx * dx + dy * dy);
return "M" + d.source.x + ","
+ d.source.y + "A" + dr + ","
+ dr + " 0 0,1 " + d.target.x + ","
+ d.target.y;
});
});



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

以上就是全部代码, 目前未实现箭头,昨天搞了好长时间, 没弄出来, Java的画图工具不行, 太丑, 现在D3Js 很火,这里做个参考