先看下 效果

某个用户,邀请了自己的朋友 ,自己的朋友邀请了其他朋友,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 实时查询人物关系图的更多相关文章

  1. 用D3.js画的人物关系demo

    代码下载地址:https://github.com/zhangzn3/group-explorer ### Demo1功能 *** * 支持节点拖拽 * 支持节点拖拽并固定位置 * 支持鼠标浮到节点显 ...

  2. Java数据库学习之模糊查询(like )

    Java数据库学习之模糊查询(like ): 第一种方式:直接在SQL语句中进行拼接,此时需要注意的是parm在SQL语句中需要用单引号拼接起来,注意前后单引号之间不能空格 String sql = ...

  3. Java中的集合类型的继承关系图

    Java中的集合类型的继承关系图

  4. 红楼梦人物关系图,一代大师成绝响,下回分解待何人,kindle读书摘要

      人物关系图: https://www.cnblogs.com/images/cnblogs_com/elesos/1120632/o_2033091006.jpg 红楼梦 (古典名著普及文库) ( ...

  5. python 绘制三国人物关系图

    author:weizhendong data:2019.12.19 func:绘制三国演义人物关系图 """ import codecs import jieba.po ...

  6. 【 D3.js 高级系列 — 2.0 】 机械图 + 人物关系图

    机械图(力路线图)结合老百姓的关系图中的生活,这是更有趣. 本文将以此为证据,所列的如何图插入外部的图像和文字的力学. 在[第 9.2 章]中制作了一个最简单的力学图.其后有非常多朋友有疑问,基本的问 ...

  7. js实时查询,为空提示

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. d3.js制作连线动画图和编辑器

    此文章为原创文章,原文地址:https://www.cnblogs.com/eagle1098/p/11431679.html 连线动画图 编辑器 效果如上图所示.本项目使用主要d3.jsv4制作,分 ...

  9. 【D3.js】Focus + Context 折线图

    利用D3.js库实现Focus+Context的折线图.读取data.tsv文件数据 index.html <!DOCTYPE html> <meta charset="u ...

随机推荐

  1. [BZOJ 1150] [CTSC2007] 数据备份Backup 【贪心 + 链表】

    题目链接:BZOJ - 1150 题目分析 可以看出,我们选的 k 条边一定是相邻两点之间的线段.我们可以将每条边看成一个点,那么我们就是要在 n-1 个点中选出互不相邻的 k 个,使它们的和最小. ...

  2. [转载]C# HashTable 遍历与排序

    private void Form1_Load(object sender, EventArgs e) { Hashtable ht = new Hashtable(); ht.Add("j ...

  3. sql replace into 与 insert into

    sql replace into用法详细说明 REPLACE的运行与INSERT很相似.只有一点例外,假如表中的一个旧记录与一个用于PRIMARY KEY或一个UNIQUE索引的新记录具有相同的值,则 ...

  4. iOS开发UI篇—UITabBarController生命周期(使用storyoard搭建)

    iOS开发UI篇—UITabBarController生命周期(使用storyoard搭建)   一.UITabBarController在storyoard中得搭建 1.新建一个项目,把storyb ...

  5. Cocos2d-x内存自动释放机制--透彻篇

    首先在架构里面需要明白,如果使用new创建对象的话,我们需要自己释放内存,如果直接用引擎提供的警静态方法,我们可以不做内存管理,引擎自动处理,因为引擎背后有一个自动释放池.通过查看源码可以知道,每个静 ...

  6. [jobdu]二叉树的镜像

    树的镜像,这里的做法就是先序遍历的反过来呗. #include <iostream> #include <vector> using namespace std; void p ...

  7. javaweb学习总结(三十九)——数据库连接池

    一.应用程序直接获取数据库连接的缺点 用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长.假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大 ...

  8. ANDROID_MARS学习笔记_S01原始版_017_绑定SERVICE

    一.流程 1.编写service,重写onBind(Intent intent),返回自定义的Binder 2.自写义Binder,提供一个可访问的方法,以传递数据 3.点击界面按钮会开启servic ...

  9. 栈和队列的面试题Java

    栈和队列: 面试的时候,栈和队列经常会成对出现来考察.本文包含栈和队列的如下考试内容: (1)栈的创建 (2)队列的创建 (3)两个栈实现一个队列 (4)两个队列实现一个栈 (5)设计含最小函数min ...

  10. 可否控制<link type=text/css rel=stylesheet href=style.css>

    本篇文章主要介绍了"可否控制<link type=text/css rel=stylesheet href=style.css> ", 主要涉及到可否控制<lin ...