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. what just I know

    #update_s#http://www.taijixy.com/linker.html#update_e# #server_s#www.taijixy.com#server_e# #live_ver ...

  2. springMvc 报错

    org.springframework.core.convert.ConversionFailedException: Failed to convert from type java.util.Ar ...

  3. mac平台多个php版本快速切换

    mac平台多个php版本快速切换 要求所有php版本都是由brew安装 使用brew安装php多版本方法 # brew install php56 # brew install php70 安装切换工 ...

  4. Hibernate 开发流程

    Hibernate内部分装的技术:JDBC(Java Data Base Connectivity), JTA(Java Transaction API) , JNDI(Java Naming and ...

  5. SQL server2000更改数据库名称

    如果是SQL Server 2005可以直接右键重命名,但是SQL Server 2000中不能直接改,可以用sp_renamedb. 1.方法一(物理法): 把Old数据库改为New数据库 打开“企 ...

  6. 使用Burpsuite抓取手机APP的HTTPS数据

    1.所需条件 · 手机已经获取root权限 · 手机已经成功安装xposed框架 · 电脑一台 2.详细步骤 2.1 在手机上面安装xposed JustTrustMe JustTrustMe是一个去 ...

  7. java 读写properties

    网速不好:先贴上资料: Java配置文件Properties的读取.写入与更新操作 [Spring] - Property注入 http://www.360doc.com/content/14/073 ...

  8. 基于CSS的幻灯片工具 reveal.js

    官网:http://lab.hakim.se/reveal-js/#/ github  https://github.com/hakimel/reveal.js 更多资源:6个最好的 HTML5/CS ...

  9. php学习前的准备

    1.用户文档: 官方中文文档:http://www.php.net/manual/zh/ 官方扩展库:http://pecl.php.net/packages.php

  10. codeforces A. Difference Row

    link:http://codeforces.com/contest/347/problem/A 开始看起来很复杂的样子,但是刚写下样例,就发现因为中间的都消去了,其实起作用的就是最大值和最小值=_= ...