做项目遇到一个需求,将具有层级关系的词语用树状图的形式展示它们之间的关系,像这样:

或者是这样:

上面的图片只是样例,跟我下面的代码里面用的数据不同

网上有很多这种数据可视化展示的js控件,我这里选择了D3.js。

首先在html页面需要包含D3的js文件,其次我们需要将数据构造成json格式,然后存入到一个d3.json文件

{
"name":"如何学习D3",
"children":
[
{
"name":"预备知识" ,
"children":
[
{"name":"HTML & CSS" },
{"name":"JavaScript" },
{"name":"DOM" },
{"name":"SVG" }
]
}, {
"name":"安装" ,
"children":
[
{
"name":"记事本软件",
"children":
[
{"name":"Notepad++"},
{"name":"EditPlus"},
{"name":"Sublime Text"}
]
},
{
"name":"服务器软件",
"children":
[
{"name":"Apache Http Server"},
{"name":"Tomcat"}
]
},
{"name":"下载D3.js"}
]
}, {
"name":"入门",
"children":
[
{
"name":"选择集",
"children":
[
{"name":"select"},
{"name":"selectAll"}
]
},
{
"name":"绑定数据",
"children":
[
{"name":"datum"},
{"name":"data"}
]
},
{"name":"添加删除元素"},
{
"name":"简单图形",
"children":
[
{"name":"柱形图"},
{"name":"折线图"},
{"name":"散点图"}
]
},
{"name":"比例尺"},
{"name":"生成器"},
{"name":"过渡"}
]
}, {
"name":"进阶" ,
"children":
[
{
"name":"布局的应用",
"children":
[
{"name":"饼状图"},
{"name":"树状图"},
{"name":"矩阵树图"}
]
},
{"name":"地图"}
]
}
]
}

然后开始编写JavaScript代码:

横向树状图:

var width = 700,
height = 700; var cluster = d3.layout.cluster()
.size([width, height - 200]); var diagonal = d3.svg.diagonal()
.projection(function(d) { return [d.y, d.x]; }); var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(40,0)"); d3.json("d3.json", function(error, root) { var nodes = cluster.nodes(root);
var links = cluster.links(nodes); console.log(nodes);
console.log(links); var link = svg.selectAll(".link")
.data(links)
.enter()
.append("path")
.attr("class", "link")
.attr("d", diagonal); var node = svg.selectAll(".node")
.data(nodes)
.enter()
.append("g")
.attr("class", "node")
.attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; }) node.append("circle")
.attr("r", 4.5); node.append("text")
.attr("dx", function(d) { return d.children ? -8 : 8; })
.attr("dy", 3)
.style("text-anchor", function(d) { return d.children ? "end" : "start"; })
.text(function(d) { return d.name; });
});

圆形树状图(这个需要用到投影,稍微麻烦一点,不详细解释了):

//图像区域大小
var R = 600; //定义一个Tree对象,定义旋转角度和最大半径
var tree = d3.layout.tree()
.size([360,R/2-120])
.separation(function(a,b) { return a.parent == b.parent ? 1 : 2;}); //定义布局方向
var diagonal = d3.svg.diagonal()
.projection(function(d) {
var r = d.y, a = (d.x-90) / 180 * Math.PI;
return [r * Math.cos(a), r * Math.sin(a)];
}); //新建画布,移动到圆心位置
var svg = d3.select("#showTree").append("svg")
.attr("width", R)
.attr("height", R)
.append("g")
.attr("transform", function(d){ return "translate("+R/2+"," + R/2 + ")";}); //根据JSON数据生成树
d3.json("d3.json", function(error, data) { //根据数据生成nodes集合
var nodes = tree.nodes(data); //获取node集合的关系集合
var links = tree.links(nodes); //为关系集合设置贝塞尔曲线连接
var link=svg.selectAll(".link")
.data(links)
.enter()
.append("path")
.attr("class", "link")
.attr("d",diagonal); //根据node集合生成节点
var node = svg.selectAll(".node")
.data(nodes)
.enter()
.append("g")
.attr("class", "node")
.attr("transform",function(d){return "rotate(" + (d.x-90) + ")translate(" + d.y + ")"; }); //为节点添加圆形标记,如果有子节点为红色,否则绿色
node.append("circle")
.attr("fill",function(d){return d.children==null?"#0F0":"#F00";})
.attr("r", 5); //为节点添加说明文字
node.append("text")
.attr("dy", ".4em")
.text(function(d){return d.name;})
.attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; })
.attr("transform", function(d) { return d.x < 180 ? "translate(8)" : "rotate(180)translate(-8)"; });
});

D3的d3.json(url,callback)方法可以读取json文件,然后构造树状图。

如果不想把数据写入json文件,直接在后台构造好json数据结构然后传到前台要怎么弄?

其实d3.json(url,callback)方法的url是发起一个get请求,返回一个json字符串,然后进入callback进行处理,本质上跟ajax差不多

所以当我们不想读取文件时,修改一下d3.json(url,callback)的url参数,发起一个get请求到控制器,然后你在控制器里面构造相应的json数据结构,然后返回过来就可以了

但是这里的url不能直接带中文参数,比如:

url = "json.html?word=关键词";

这样的请求发到后台,后台接收的是这样的一段乱码字符串:

关键è¯

那有人说先将这个中文做一次编码,然后在传到后台不就行了?

确实,我们一般在js里面如果要传中文参数到后台都会先进行编码然后再传的,所以我当时也是这么想的,心想这下应该不会出问题了吧,然并卵,后台接收然后解码得到的依然是那串乱码,然后没办法,我只能进d3.js的文件去查看源码,奈何才疏学浅,压根看不懂,也没找到它哪里对这个url做了什么编码或解码操作。后来想到以前见到过在前台进行多次编码然后再传到后台的,我也尝试了一下在js里面进行了两次编码,然后再传到后台,到后台接收然后解码一次,发现能够得到正确的中文参数

第一行是后台接收的参数,第二行是对参数解码一次得到的结果。

问题是解决了,但是我还是不知道这是为什么,只注意到d3.json这个方法里面发送的是get请求,后来查资料还有问其他人才知道在浏览器地址栏里,浏览器认为%是个转义字符,浏览器会把%与%之间的编码,两位两位取出后进行解码,然后再传递给处理页面,然后由处理页面进行再次解码,而get请求的中文参数就是显示在浏览器地址栏,所以在js里面参数只进行一次编码的话,参数经过浏览器的解码,传到后台的就是没编码的中文,这个当然就会变成乱码,所以在js里面对中文做两次编码然后通过get请求传到后台,后台只需做一次解码就能得到正确的中文参数

用D3.js画树状图的更多相关文章

  1. D3.js画思维导图(转)

    思维导图的节点具有层级关系和隶属关系,很像枝叶从树干伸展开来的形状.在前面讲解布局的时候,提到有五个布局是由层级布局扩展来的,其中的树状图(tree layout)和集群图(cluster layou ...

  2. D3.js:饼状图的制作

    假设有如下数据需要可视化: var dataset = [ 30 , 10 , 43 , 55 , 13 ]; 这样的值是不能直接绘图的.例如绘制饼状图的一个部分,需要知道一段弧的起始角度和终止角度, ...

  3. canvas+js画饼状图

    效果: 源码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...

  4. d3生成的树状图

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

  5. D3树状图给指定特性的边特别显示颜色

    D3作为前端图形显示的利器,功能之强,对底层技术细节要求相对比较多. 有一点,就是要理解其基本的数据和节点的匹配规则架构,即enter,update和exit原理,我前面的D3基础篇中有介绍过,不明白 ...

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

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

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

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

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

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

  9. visio画等分树状图

    一 树状图形状 Search里搜索Tree,找到Double Tree或者Multi Tree的形状 二 分出更多branch 按住主干上的黄色小方块,拖出更多分支. 三 等分分支 将每个分支和对应的 ...

随机推荐

  1. 【转】23 个安卓重难点突破,带你吃透 Service 知识点「长达 1W+ 字」

    前言 学 Android 有一段时间了,想必不少人也和我一样,平时经常东学西凑,感觉知识点有些凌乱难成体系.所以趁着这几天忙里偷闲,把学的东西归纳下,捋捋思路. 这篇文章主要针对 Service 相关 ...

  2. Nodejs介绍和环境搭建

    Nodejs是JavaScript的运行环境,它让 Java Script 可以开发后端程序,实现几乎其他后端 Node.js 是一个 Javascript 运行环境(runtime) 可以与 PHP ...

  3. SDN实验---使用git安装Mininet

    0:补充Ubuntu截屏 截全屏 printscreen 截取当前窗口 alt + printscreen 截取任意矩形 shift + printscreen 截取全屏到剪切板 ctrl + pri ...

  4. matlab学习笔记7-定时器

    一起来学matlab-matlab学习笔记7-定时器 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考书籍 <matlab 程序设计与综合应用>张德丰等著 感谢张老师的书籍,让 ...

  5. [LeetCode] 248. Strobogrammatic Number III 对称数III

    A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at upside ...

  6. pytest+allure测试框架搭建

    https://blog.csdn.net/wust_lh/article/details/86685912 https://www.jianshu.com/p/9673b2aeb0d3 定制化展示数 ...

  7. [转] Win10插入U盘后双击无法打开,无法访问,显示设备未就绪;驱动哥帮你解决

    说起U盘,相信大家都不陌生. 这个不起眼的小东西在我们日常生活息息相关,一旦损坏可能就会造成一些不必要的麻烦. 最近驱动哥就收到了一大批用户关于U盘问题的相关咨询,一起来看看到底是什么情况吧! 据其中 ...

  8. Delphi 10 Seattle plus 新特性——System.JSON.Builders

    { 全能中间件 —— 简单.高效.稳定.安全的三层中间件 1.支持 多账套多数据库,包括SQLite, MySQL, SQL Server, Oracle, PostgreSQL, DB2, SQL ...

  9. linux初识1

    linux 操作系统 概念性的理解 1.Linux内置解释器bash 相当于pyhon解释器 2.Linux的内部大多是使用python去书写 云计算 1.只需要 花钱,买腾讯,阿里云服务器 2.专人 ...

  10. PAT(B) 1045 快速排序(C)

    题目链接:1045 快速排序 (25 point(s)) 参考博客:1045 快速排序 (25 point(s))繁星蓝雨 题目描述 著名的快速排序算法里有一个经典的划分过程:我们通常采用某种方法取一 ...