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

或者是这样:

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

网上有很多这种数据可视化展示的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. [转]Vue-Devtools安装配置教程(献给伸手党)

    原文地址:https://blog.csdn.net/weixin_38654336/article/details/80790698 可以先看视频教程:链接 最简便的方法是用FQ来通过google应 ...

  2. python中video system not initialized怎么解决

    今天在github上找到一个用pygame做的Python游戏,但是clone到本地运行的时候却冒出了“mixer system not initialized”这样的问题.其实这句话说的就是音频混音 ...

  3. 配置mongo.conf文件

    配置mongo.conf文件,优化mongod.exe的启动 在d:/Develop/MongoDB目录下创建mongo.conf文件并写入:   dbpath=d:\Develop\MongoDB\ ...

  4. 2-4 【接口Interface Flex布局】让顶部导航滚动

    可以把复杂的类型做命名.例如接口中没有定义年龄,在定义person的时候 如果写了age那么就会报错.因为我们接口中并没有定义年龄. 可选属性,只读属性 新的布局方式 下面这里menu设置类型为Top ...

  5. matlab学习笔记4--导入和导出Internet数据

    一起来学matlab-matlab学习笔记4 数据导入和导出_4 导入和导出Internet数据 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考书籍 <matlab 程序设计与综合 ...

  6. IISExpress.无法启动IIS Express Web 服务器.Starting IIS Express... IIS Express is running

    x 提示: 无法启动IIS Express Web 服务器. 来自IIS Express的输出: Starting IIS Express... IIS Express is running 总结: ...

  7. 导入一个eclipse的java项目到IDEA报Cannot find JDK '1.7' for module 'TEST'

    解决办法: 右键你的项目--------------->OPen module settings 将dependencies里面的module sdk改成你安装的java版本就可以了(比如我电脑 ...

  8. [LeetCode] 45. Jump Game II 跳跃游戏 II

    Given an array of non-negative integers, you are initially positioned at the first index of the arra ...

  9. Float在内存中的存储方式及IEC61131处理

    Float在内存中的存储方式及IEC61131处理 1,fp32(32bits float)类型数据在存储器中占用4Bytes存储,且遵循IEEE-754标准: 一个浮点数分三部分组成: 符号位s(1 ...

  10. Windows 下使用 Composer 安装 thinkphp

    我用 XAMPP 安装 thinkphp 会出错,所以把环境换成了 phpStudy,这样甚至不用到处找安装包,直接去官网有最新版本,PHP 版本也是比较新的. 安装 phpStudy 先去官网下载安 ...