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 数据库 因为数据库暂时没有用户头像,所以随机工具类定义了几个头像

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, 下面是 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 很火,这里做个参考
java+数据库+D3.js 实时查询人物关系图的更多相关文章
- 用D3.js画的人物关系demo
代码下载地址:https://github.com/zhangzn3/group-explorer ### Demo1功能 *** * 支持节点拖拽 * 支持节点拖拽并固定位置 * 支持鼠标浮到节点显 ...
- Java数据库学习之模糊查询(like )
Java数据库学习之模糊查询(like ): 第一种方式:直接在SQL语句中进行拼接,此时需要注意的是parm在SQL语句中需要用单引号拼接起来,注意前后单引号之间不能空格 String sql = ...
- Java中的集合类型的继承关系图
Java中的集合类型的继承关系图
- 红楼梦人物关系图,一代大师成绝响,下回分解待何人,kindle读书摘要
人物关系图: https://www.cnblogs.com/images/cnblogs_com/elesos/1120632/o_2033091006.jpg 红楼梦 (古典名著普及文库) ( ...
- python 绘制三国人物关系图
author:weizhendong data:2019.12.19 func:绘制三国演义人物关系图 """ import codecs import jieba.po ...
- 【 D3.js 高级系列 — 2.0 】 机械图 + 人物关系图
机械图(力路线图)结合老百姓的关系图中的生活,这是更有趣. 本文将以此为证据,所列的如何图插入外部的图像和文字的力学. 在[第 9.2 章]中制作了一个最简单的力学图.其后有非常多朋友有疑问,基本的问 ...
- js实时查询,为空提示
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- d3.js制作连线动画图和编辑器
此文章为原创文章,原文地址:https://www.cnblogs.com/eagle1098/p/11431679.html 连线动画图 编辑器 效果如上图所示.本项目使用主要d3.jsv4制作,分 ...
- 【D3.js】Focus + Context 折线图
利用D3.js库实现Focus+Context的折线图.读取data.tsv文件数据 index.html <!DOCTYPE html> <meta charset="u ...
随机推荐
- 在JSP中使用BootStrap
1. 下载BootStrap,然后再Jsp标签中添加如下标签: <html> <head lang="zh-cn"> <meta charset=&q ...
- 机器学习算法与Python实践之(二)支持向量机(SVM)初级
机器学习算法与Python实践之(二)支持向量机(SVM)初级 机器学习算法与Python实践之(二)支持向量机(SVM)初级 zouxy09@qq.com http://blog.csdn.net/ ...
- POJ2301+水~~~~~~
有比这更水的么.............. #include<stdio.h> int main(){ int n; scanf("%d",&n); while ...
- 服务器部署_centos 安装jdk手记
1. 下载jdk略. 2. 将jdk相关文件目录放到指定目录 (1) 创建jdk目录 /usr/java/jdk7 mkdir -p /usr/java/jdk7 (2) 解压缩jdk压缩包,并移动至 ...
- YIi 权限管理和基于角色的访问控制
验证和授权(Authentication and Authorization) 定义身份类 (Defining Identity Class) 登录和注销(Login and Logout) 访问控制 ...
- Android:WebView深入使用
webView = (WebView) findViewById(R.id.info_detail_webview); WebSettings webSettings = webView.getSet ...
- 公司估值(贴现现金流量法DCF)
创业公司总会遇到并购或者入股等情况,CEO需要了解一些公司估值的方法,本文主要介绍贴现现金流量估值方法,供大家参考: 中国资产评估协会要求:在对企业价值进行评估时,应分析收益法.市场法和资产基础法三种 ...
- ubunt下的MinimalCD
ubuntu有MinimalCD,水平高的衍生版制作者基于MinimalCD安装并编译,定制出独特风格的ubuntu衍生版,如 crunchbang.水平不高的个人用户可以从Alternate(文字安 ...
- c程序设计语言_习题1-13_统计输入中单词的长度,并且根据不同长度出现的次数绘制相应的直方图
Write a program to print a histogram of the lengths of words in its input. It is easy to draw the hi ...
- 负载均衡服务器session共享的解决方案
在ASP.NET的程序中要使用Session对象时,必须确保页面的@page指令中EnableSessionState属性是True或者Readonly,并且在web.config文件中正确的设置了S ...