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

或者是这样:

上面的图片只是样例,跟我下面的代码里面用的数据不同
网上有很多这种数据可视化展示的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画树状图的更多相关文章
- D3.js画思维导图(转)
思维导图的节点具有层级关系和隶属关系,很像枝叶从树干伸展开来的形状.在前面讲解布局的时候,提到有五个布局是由层级布局扩展来的,其中的树状图(tree layout)和集群图(cluster layou ...
- D3.js:饼状图的制作
假设有如下数据需要可视化: var dataset = [ 30 , 10 , 43 , 55 , 13 ]; 这样的值是不能直接绘图的.例如绘制饼状图的一个部分,需要知道一段弧的起始角度和终止角度, ...
- canvas+js画饼状图
效果: 源码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...
- d3生成的树状图
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- D3树状图给指定特性的边特别显示颜色
D3作为前端图形显示的利器,功能之强,对底层技术细节要求相对比较多. 有一点,就是要理解其基本的数据和节点的匹配规则架构,即enter,update和exit原理,我前面的D3基础篇中有介绍过,不明白 ...
- D3.js系列——布局:弦图和集群图/树状图
一.弦图 1.弦图是什么 弦图(Chord),主要用于表示两个节点之间的联系的图表.两点之间的连线,表示谁和谁具有联系. 2.数据 初始数据为: var city_name = [ "北京& ...
- d3.js(v5.7)树状图
一.新建画布 二.数据处理 三.绘制连接线 图示: 四.绘制节点.文字 图示: 五.总结 path元素:其实就是定义了绘图的坐标点,从哪开始,移动到哪,怎样移动(命令) 具体可百度(或许以后我会总结一 ...
- D3树状图异步按需加载数据
D3.js这个绘图工具,功能强大不必多说,完全一个Data Driven Document的绘图工具,用户可以按照自己的数据以及希望实现的图形,随心所欲的绘图. 图形绘制,D3默认采用的是异步加载,但 ...
- visio画等分树状图
一 树状图形状 Search里搜索Tree,找到Double Tree或者Multi Tree的形状 二 分出更多branch 按住主干上的黄色小方块,拖出更多分支. 三 等分分支 将每个分支和对应的 ...
随机推荐
- 搭建redis cluster集群服务
redis 5.0以下为ruby编写,运行命令时需要安装ruby,而5.0以上则为c编写,可直接安装后运行.因此本文使用redis5.0.5 1.编写配置文件 在 /home 下新建 redis-cl ...
- HTTP协议复习
HTTP请求/响应的步骤: 客户端连接到WEB服务器:浏览器与web服务器的HTTP端口建立一个TCP套接字连接,例如:http://www.baidu.com 发送HTTP请求:通过TCP套接字,客 ...
- 【LeetCode算法-21】Merge Two Sorted Lists
LeetCode第21题 Merge two sorted linked lists and return it as a new list. The new list should be made ...
- Python爬虫笔记技术篇
目录 前言 requests出现中文乱码 使用代理 BeautifulSoup的使用 Selenium的使用 基础使用 Selenium获取网页动态数据赋值给BeautifulSoup Seleniu ...
- IFC文件介绍
IFC是一个数据交换标准, 用于不同系统交换和共享数据. IFC是采用EXPRESS语言定义的实体关系模型,由几百个实体对象组成.实体对象包括建筑要素如IfcWall,几何元素如IfcExtruded ...
- Metricbeat 轻量型指标采集器
一.介绍 用于从系统和服务收集指标.从 CPU 到内存,从 Redis 到 Nginx,Metricbeat 能够以一种轻量型的方式,输送各种系统和服务统计数据. 1.系统级监控,更简洁(轻量型指标采 ...
- 微信小程序 与后台交互----获取服务器时间
index.wxml代码 <!--index.wxml--> <view class="container"> <text>{{date}}&l ...
- js arguments
偶然碰见一个有意思的题 <script> var length = 10; function fn() { console.log( this.length ); // 10 } var ...
- springboot继承JpaRepository报org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualif
在SpringBoot项目中使用JPA时总是报注入失败,不能创建继承JpaRepository的类的问题,然后尝试给继承JpaRepository的写个实现类,不出现注入失败的情况,但是过一段时间后继 ...
- 关于st表
#include<cstdio> #include<iostream> #include<cmath> #include<cctype> #includ ...