用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 按住主干上的黄色小方块,拖出更多分支. 三 等分分支 将每个分支和对应的 ...
随机推荐
- 【idea】idea学习手册
学习笔记:https://www.w3cschool.cn/intellij_idea_doc/intellij_idea_doc-q3ke2coy.html 断点调试:https://www.cnb ...
- web编辑器的使用比较
一开始测试的时候发现都还可以,只是出于后续考虑,选择了ckeditor,但是有时候会莫名出现Cannot read property 'XXX' of undefined,如下: Uncaught T ...
- ajax发送json数据时为什么需要设置contentType: "application/json”
1. ajax发送json数据时设置contentType: "application/json”和不设置时到底有什么区别?contentType: "application/js ...
- rabbitmq - 消息接收,解析xml格式数据时异常:ERROR not well-formed (invalid token): line 4, column 46
ERROR alsv odoo.addons.cus_alsv.utils.alsv_about_mq.get_data_from_mq: parse_xml_data_from_mq: not we ...
- Coder 健康 知识
- [图片问答]lodop注册相关
相关博文:LODOP和C-LODOP注册与角色等简短问答[增强版]由于其他博文要么图片太花哨(PS做的所以太花哨),要么文字太啰嗦,所以做了简短问答的图片,更简洁直观方便.1.该购买哪种LODOP注册 ...
- [LeetCode] 369. Plus One Linked List 链表加一运算
Given a non-negative number represented as a singly linked list of digits, plus one to the number. T ...
- LeetCode:接雨水【42】
LeetCode:接雨水[42] 题目描述 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水. 上面是由数组 [0,1,0,2,1,0,1,3,2,1, ...
- aspose.slides for java去除水印
前一段时间使用aspose.slides for java,处理了下才去除的水印,但是时间一久就忘记了,重新整理了下 下载aspose-slides-19.3-jdk16.jar,重命名为aspose ...
- 玩转CONSUL(3)–大规模部署的性能开销定量分析
1. 引言 今天有朋友问萌叔,consul能否在大规模生产环境下进行应用.场景是总计大约10w+台机器,分为3 ~ 4个机房,单个机房最多3w万+机器.这个问题大的,可把萌叔吓了跳,部门里面consu ...