D3作为前端图形显示的利器,功能之强,对底层技术细节要求相对比较多。

有一点,就是要理解其基本的数据和节点的匹配规则架构,即enter,update和exit原理,我前面的D3基础篇中有介绍过,不明白的可以再去研究下。

本篇博文,同样是在这个框架下,完成修改树状图中某两个节点之间的边用红色线条连接,实现表达特殊含义的目的。

背景故事: 微信朋友圈之间产品帖子相互转发,有些帖子转发后会有成交,只要有成交,则这个促成成交的节点及其之上的父节点都相应是有功劳的,这个轨迹需要用高亮的颜色表示(比如本例中,用红色表示)。

其实也比较简单,直接看代码, 前端部分:

 <!DOCTYPE html>
<meta charset="utf-8">
<style> .node {
cursor: pointer;
} .node circle {
fill: #fff;
stroke: steelblue;
stroke-width: .5px;
} .node text {
font: 10px sans-serif;
} .link {
fill: none;
stroke: #ccc;
stroke-width: .5px;
} .link2 {
fill: none;
stroke: #f00;
stroke-width: 1.5px;
} </style>
<body>
<script src="js/jquery-2.1.1.min.js" charset="utf-8"></script>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script>
var root = {
"name": "flare",
"deal": "2",
"children": [{
"name": "analytics" ,
"children": [{
"name": "cluster",
"children": [{
"name": "AgglomerativeCluster",
"size":
}, {
"name": "CommunityStructure",
"size":
}, {
"name": "HierarchicalCluster",
"size":
}, {
"name": "MergeEdge",
"size":
}]
}]
}, {
"name": "ISchedulable",
"deal": "2",
"size":
}, {
"name": "Parallel",
"size":
}, {
"name": "Pause",
"size":
}
]
};
var margin = {top: , right: , bottom: , left: },
width = - margin.right - margin.left,
height = - margin.top - margin.bottom; var i = ,
duration = ,
root; var tree = d3.layout.tree().nodeSize([, ]); var diagonal = d3.svg.diagonal()
.projection(function(d) { return [d.x, d.y]; }); //Redraw for zoom
function redraw() {
//console.log("here", d3.event.translate, d3.event.scale);
svg.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")");
} var svg = d3.select("body").append("svg").attr("width", ).attr("height", )
.call(zm = d3.behavior.zoom().scaleExtent([,]).on("zoom", redraw)).append("g")
.attr("transform", "translate(" + + "," + + ")"); //necessary so that zoom knows where to zoom and unzoom from
zm.translate([, ]); //d3.json("flare.json", function(error, flare)
// if (error) throw error; root.x0 = ;
root.y0 = height / ; function collapse(d) {
if (d.children) {
d._children = d.children;
d._children.forEach(collapse);
d.children = null;
}
} root.children.forEach(collapse);
update(root); d3.select(self.frameElement).style("height", "800px"); function update(source) { // Compute the new tree layout.
var nodes = tree.nodes(root).reverse(),
links = tree.links(nodes); // Normalize for fixed-depth.
nodes.forEach(function(d) { d.y = d.depth * ; }); // Update the nodes…
var node = svg.selectAll("g.node")
.data(nodes, function(d) { return d.id || (d.id = ++i); }); // Enter any new nodes at the parent's previous position.
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) { return "translate(" + source.x0 + "," + source.y0 + ")"; })
.on("click", click); nodeEnter.append("circle")
.attr("r", 1e-)
.style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; }); nodeEnter.append("text")
.attr("cx", function(d) { return d.children || d._children ? - : ; })
.attr("cy", ".35em")
.attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; })
.text(function(d) { return d.name; })
.style("fill-opacity", 1e-); // Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); nodeUpdate.select("circle")
.attr("r", )
.style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; }); nodeUpdate.select("text")
.style("fill-opacity", ); // Transition exiting nodes to the parent's new position.
var nodeExit = node.exit().transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + source.x + "," + source.y + ")"; })
.remove(); nodeExit.select("circle")
.attr("r", 1e-); nodeExit.select("text")
.style("fill-opacity", 1e-); // Update the links…
var link = svg.selectAll("path.link")
.data(links, function(d) { return d.target.id; }); // Enter any new links at the parent's previous position.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", function(d) {
var o = {x: source.x0, y: source.y0};
return diagonal({source: o, target: o});
}); // Transition links to their new position.
link.transition()
.duration(duration)
.attr("d", diagonal)
.attr("class", function(d){
if(d.source.deal != null && d.source.deal != undefined){
if(d.target.deal != null && d.target.deal != undefined){
return "link link2";
}
}
return "link";
}); // Transition exiting nodes to the parent's new position.
link.exit().transition()
.duration(duration)
.attr("d", function(d) {
var o = {x: source.x, y: source.y};
return diagonal({source: o, target: o});
})
.remove(); // Stash the old positions for transition.
nodes.forEach(function(d) {
d.x0 = d.x;
d.y0 = d.y;
});
} function getNode(){
var mynodes = null;
$.ajax({
url : "./node",
async : false, // 注意此处需要同步,因为返回完数据后,下面才能让结果的第一条selected
type : "POST",
dataType : "json",
success : function(data) {
mynodes = data;
console.log(mynodes);
//nodes = JSON.parse(nodes);
}
});
return mynodes;
} // Toggle children on click.
function click(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else if(d._children){
d.children = d._children;
d._children = null;
}else {
var mnodes = getNode();
d.children = mnodes.children;
}
update(d);
} </script>

整个前端的代码,重点看其中红色标识的部分,这些部分是和这个博文的内容直接相关的。 涉及到连接的红色标识。 数据中定义了deal字段,这个字段就是标识某个节点具有这个特性,只有这个特性的节点之间的边用红色标识。 另外,点击按钮,异步加载后端服务器的代码部分,也有部分数据是含有这个deal特性的,同样适用于本故事的要求。

在代码的186行中,link的transition(即变化,变换)过程中,去渲染节点之间的边的样式。其实,还可以在其他地方做这个样式的加载,比如在link的enter部分实现,只是这个过程,有点违背D3架构设计之enter,update和exit的大前提,不建议在enter里面实现这个功能。

后端的代码,只是一个示例代码,和前面D3博文的基本相同:

 /**
* @author "shihuc"
* @date 2016年11月14日
*/
package com.tk.es.search.controller; import java.util.ArrayList;
import java.util.HashMap; import javax.servlet.http.HttpServletRequest; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; import com.google.gson.Gson; /**
* @author chengsh05
*
*/
@Controller
public class D3Controller { @RequestMapping(value = "/d3")
public String d3Page(HttpServletRequest req){
return "d3demo2";
} @RequestMapping(value = "/node")
@ResponseBody
public String asyncGet(HttpServletRequest req){
HashMap<String, Object> data = new HashMap<String, Object>();
ArrayList<Object>elem1 = new ArrayList<Object>();
HashMap<String, String> elem1e = new HashMap<String, String>();
elem1e.put("name", "one");
elem1e.put("deal", "2");
HashMap<String, String> elem2e = new HashMap<String, String>();
elem2e.put("name", "two");
HashMap<String, String> elem3e = new HashMap<String, String>();
elem3e.put("name", "three");
elem1.add(elem1e);
elem1.add(elem2e);
elem1.add(elem3e); data.put("name", "Pause");
data.put("children", elem1); Gson gson = new Gson();
return gson.toJson(data);
}
}

上述代码,表明只有节点名为one的节点,给其配置deal属性值,也就是说在最终D3绘制的树状图上,名为one的节点间会出现红色link。

最终效果图如下,首先看默认显示的情况

点击显示one节点之间的状态

D3树状图给指定特性的边特别显示颜色的更多相关文章

  1. D3树状图异步按需加载数据

    D3.js这个绘图工具,功能强大不必多说,完全一个Data Driven Document的绘图工具,用户可以按照自己的数据以及希望实现的图形,随心所欲的绘图. 图形绘制,D3默认采用的是异步加载,但 ...

  2. D3.js系列——布局:弦图和集群图/树状图

    一.弦图 1.弦图是什么 弦图(Chord),主要用于表示两个节点之间的联系的图表.两点之间的连线,表示谁和谁具有联系. 2.数据 初始数据为: var city_name = [ "北京& ...

  3. 用D3.js画树状图

    做项目遇到一个需求,将具有层级关系的词语用树状图的形式展示它们之间的关系,像这样: 或者是这样: 上面的图片只是样例,跟我下面的代码里面用的数据不同 网上有很多这种数据可视化展示的js控件,我这里选择 ...

  4. d3.js(v5.7)树状图

    一.新建画布 二.数据处理 三.绘制连接线 图示: 四.绘制节点.文字 图示: 五.总结 path元素:其实就是定义了绘图的坐标点,从哪开始,移动到哪,怎样移动(命令) 具体可百度(或许以后我会总结一 ...

  5. ztree 文件夹类型的 树状图

    未套程序的源代码: 链接:http://pan.baidu.com/s/1nuHbxhf 密码:4aw2 已套程序的源代码: css样式: /*发布邮件 选择领导弹窗*/ .xuandao{ disp ...

  6. ArcGIS教程:树状图

    摘要 构造可显示特征文件里连续合并类之间的属性距离的树示意图(树状图). 使用方法 · 输入特征文件必须採用预定的特征文件格式. 特征文件可使用 Iso 聚类或创建特征工具来创建.该文件必须至少包括两 ...

  7. 树状图展示终端目录内容-tree

    以树状图列出目录的内容,让你一目了然 执行 tree 指令,它会列出指定目录下的所有文件,包括子目录里的文件. 安装 我们通过包管理工具可以方便的安装它 mac - brew install tree ...

  8. SqlServer-无限递归树状图结构设计和查询

    在现实生活中,公司的部门设计会涉及到很多子部门,然后子部门下面又存在子部门,形成类似判断的树状结构,比如说评论楼中楼的评论树状图,职位管理的树状图结构等等,实现类似的树状图数据结构是在开发中经常出现的 ...

  9. Android开源图表之树状图和饼状图的官方示例的整理

    最近由于工作需要,所以就在github上搜了下关于chart的三方框架 官方地址https://github.com/PhilJay/MPAndroidChart 由于工作需要我这里整理了一份Ecli ...

随机推荐

  1. 普通硬件就能破解GSM A5加密算法

    如果你还在使用基于早期信号标准的GSM手机,那么你最好在使用手机的过程中小心一点了.因为根据国外媒体的最新报道,安全研究专家通过测试发现,他们只需要使用三张NVIDIA GeForce GTX690显 ...

  2. 使用恶意USB设备解锁 Windows & Mac 锁屏状态

    NSA专业物理入侵设备——USB Armory,可解锁任意锁屏状态的下的Windows和Mac操作系统,含最新发布的Windows10.及较早的Mac OSX El Capitan / Maveric ...

  3. 利用SegmentedControl切换控制器的view

    #import "ViewController.h" #import "OneViewController.h" #import "TwoViewCo ...

  4. BZOJ 3270 && BZOJ 1778 (期望DP && 高斯消元)

    BZOJ 3270 :设置状态为Id(x,y)表示一人在x,一人在y这个状态的概率. 所以总共有n^2种状态. p[i]表示留在该点的概率,Out[i]=(1-p[i])/Degree[i]表示离开该 ...

  5. fork函数创建新进程过程分析

    gdb调试执行流程,首先设置断点b sys_clone,当在shell下输入fork命令后,系统执行至断点,接下来按步执行: 判断是否被跟踪 判断是否被创建为轻量级进程(vfork) 判断父进程是否被 ...

  6. Doherty Threshold

    Prior to the publication of the IBM technical paper behind what commonly known today as the Doherty ...

  7. 贝叶斯网引论 by 张连文

    贝叶斯网(Bayesian networks)是一种描述随机变量之间关系的语言,构造贝叶斯网是为了概率推理,理论上概率推理基于联合概率分布就行了,但是联合概率分布(基于表)的复杂度会呈指数增长,贝叶斯 ...

  8. Python学习-day2

    这周时间充裕,把第一周的两个作业登陆验证和三级菜单做完后又用零零散散的时间看完了第二周的课程,不得不说老男孩这个教育方式感觉还是不错的,其实说白了就是花钱找个人监督自己学习呗,而且还强行让我们养成一些 ...

  9. NGUI实现ScrollView功能

    NGUI,目前Unity3D Assert Store中最火的2D图形界面工具. 本文假设读者有Unity3D使用经验.有基本了解.NGUI3.6.0 1.新建Pannel(Scroll View), ...

  10. java考核完的心得

    2015年8月13日     星期四      晴 今天上午我们考核了java,就是用Java语言写一个小型的管理系统.考核前的我信心满满,因为我本身是测试专业的,觉得在开发这方面对自己不用要求的那么 ...