文章目录:
引言
可是我们项目不打算用过低版本,于是我结合网上demo和d3文档,各种谷歌百度,总算是用最新版本实现了一些demo。想到好久没有记录学习到的技术了,趁此机会写下这篇 d3.js可视化开发快速入门博客,与大家交流分享。
1. D3js 是什么
近年来,数据可视化越来越流行,许多拥有大量数据的大型网站都开始使用可视化技术,使得大量杂乱的数据规则起来,易于理解,真可谓“一图胜千言”,毫不夸张。正是在这种趋势的催动下,各种数据化工具如井喷式的发展,而D3,Echarts正是其中的佼佼者。
D3 的全称是(Data-DrivenDocuments),顾名思义是一个被数据驱动的文档。其实是对数据进行可视化的JavaScript库。D3将强大的可视化和交互技术与数据驱动的DOM操作方法相结合,能最大限度地使用现代浏览器的性能同时为设计可视化界面保留了最大的自由度。D3强调Web标准,所以无需将自己与专有框架联系起来。
D3js 是一个可以基于数据来操作文档的 JavaScript 库。可以帮助你使用 HTML, CSS, SVG 以及 Canvas 来展示数据。D3 遵循现有的 Web 标准,可以不需要其他任何框架独立运行在现代浏览器中,它结合强大的可视化组件来驱动 DOM 操作。
D3 可以将数据绑定到 DOM 上,然后根据数据来计算对应 DOM 的属性值。例如你可以根据一组数据生成一个表格。或者也可以生成一个可以过渡和交互的 SVG 图形。
D3 不是一个框架,因此也没有操作上的限制。没有框架的限制带来的好处就是你可以完全按照自己的意愿来表达数据,而不是受限于条条框框,非常灵活。D3 的运行速度很快,支持大数据集和动态交互以及动画。
2. D3js 相对其他数据可视化方案的优势
对比D3和ECharts之前,先对比下两种浏览器图形渲染技术Canvas和SVG的主要区别,基本上所有的浏览器可视化第三方库都是基于这两种浏览器图形渲染技术实现的:
2.1 SVG 对比 Canvas
| SVG | Canvas |
|---|---|
| 矢量图不依赖分辨率,放大不失真 | 位图依赖分辨率 |
| 基于XML支持DOM事件处理器,SVG中每个图形节点都是单独的DOM节点可以附加js事件 | 不支持事件处理器 如果要为细粒度的元素添加事件,就需要边缘检测算法,无疑增加了难度而且不一定能保证十分精确 |
| 适合带有大型渲染区域的应用(比如:地图(每个节点区域都比较大,节点不是很多)) | 最适合图像密集型的应用比如游戏 能够方便的保存结果图像 |
| 复杂度高会减慢渲染速度(任何过度使用DOM的应用都快不了) | 一旦图形绘制完成,就不会再得到浏览器的关注 如果位置或者大小变化整个区域都要重新绘制 |
| 可以使用CSS 文本渲染能力较强 | 文本渲染能力较弱 |
Canvas比较适合事件交与较少,文本较少,或者数据量大画面刷新快的场景。
2.2 D3.js 对比 Echarts
| ECharts | D3 |
|---|---|
| Canvas为主4.0+也支持SVG | SVG为主4.0+也支持Canvas |
| 提供很多图表通过简单配置可以满足大部分需求 | 不能通过简单配置实现大部分图表 |
| 基本不可定制 | 自由度很大,基本可以自己绘制任何图表 |
| 提供完善中文文档,示例功能完善 | 提供完善英文文档,3.x版本中文文档比较完善,之后翻译的不完善,部分翻译可能需求查看英文方便理解,大部分示例需要完善才能使用,主要是参考价值 |
| 开发效率高,通过快速配置即可完成 | 大部分图表需要开发 |
| 大数据量性能较好 | 需要实现时手动优化 例如virtual DOM |
| 提供基于WebGl的GL版实现3D图表 | 借助其他库来实现例如:three.js、glMatrix、Sylvester |
总结:
ECharts等提供的图表的确可以满足大部分的需求,遵循了数据可视化的一些经典范式,一切皆可配置。然而,每个不同的行业对于数据可视化都会有一些定制化的需求,希望能以一些带有行业特征的图表向使用者展示数据背后隐藏的秘密,但是ECharts这类图形库基本不可定制,而D3自由度度很大,基本可以自己绘制任何想要的图形,这类情况的需求可以使用D3进行二次开发,定制适合的图表,但是开发成本会稍高。因此,开发中要根据实际情况来判断。无论采用哪种方式开发都要做好二次封装,把实现的图表成可复用的组件。
ECharts,hightchart这类可视化库,经过配置即可完成图表的绘制,D3要稍微麻烦一点。
使用D3绘图需要:
- 熟悉SVG(canvas)作图、熟悉CSS
- 熟悉D3的API
- 学习D3.js的编程风格
总结:D3和ECharts,hightchart这类可视化库相比属于可视化中较为基础的工具库,需要一定的可视化方面的基础才能比较快速开发出较复杂的图表,可以先尝试实现简单的图形,官网首页上面就大部分酷炫的在线Demo,难度较高可以先从demo网址找些简单点来实现
3. 怎么用 D3.js 开发一个树图
3.1 前置基础
<!-- 常用标签 --> <svg></svg> <g></g> <circle> <path> <line> <rect> <text> ... <!-- 常用属性 --> width height color transform fill stroke class d ...
3.2 d3开发树图流程
- 根据需求确定图表类型(例如树图)
- 数据预处理(把输入的原始数据转化成为标准的D3可接受的数据格式一般图像是对象数组)
- 根据处理好的数据结合布局API作图(例如树图 :d3.hierarchy()和d3.tree()的结合使用)
- 再调整文本位置,间隔等细节的东西,从而让图形布局更合理
- 给已经完成的图形添加动画效果和事件交互
3.3 动手实现一个树图
3.3.1 普通tide tree
// 1、 选中页面给页面添加svg标签;设置Svg绘制区域的宽和高;添加g元素(svg的group分组标签元素)并设置位置。 // Set the dimensions and margins of the diagram let margin = {
top: 470, right: 90, bottom: 30, left: 90 }; let width = 1960 - margin.left - margin.right; let height = 1200 - margin.top - margin.bottom; let svg = d3 .select("body") .append("svg") .attr("width", width) .attr("height", height) .append("g") .attr("transform", `translate(${
margin.left},${
margin.top})`);
第二步:数据预处理
// 2、生成树状布局,设置树图布局容器尺寸。 let tree = d3.tree().nodeSize([30, 170]); let root = d3.hierarchy(this.treeData); // 第一次数据预处理,给每个节点添加了 height depth parent 属性 this.tree(root); // 第二层数据预处理 确定每个节点在图上的位置,每个节点多了x,y属性
第三步:生成节点和链接
// 4.2生成连线。 let link = svg .selectAll(".link") .data(links) // .enter() // .append("path") .join("path") .attr("class", "link") .attr("fill", "none") .attr("stroke", "#ccc") .attr("d", diagonal); // 4.3生成节点。 let node = svg .selectAll(".node") .data(nodes) .enter() .append("g") .attr("class", "node") .attr("transform", function (d) {
return "translate(" + d.y + "," + d.x + ")"; }) // 4.4给节点添加圆圈,设置半径。 node.append("circle").attr("r", 5); // 4.5给节点添加文本,设置文本的样式位置。 node .append("text") .text((d) => {
console.log("d", d); return d.data.name; }) .attr("dx", (d) => (d.children ? -15 : 15)) .attr("dy", 5) .attr("text-anchor", (d) => (d.children ? "end" : "start"));
第四步:给已经完成的图形添加动画效果和事件交互,例如这里给每个节点添加点击事件和mouseover事件
// 4.3生成节点。 let node = svg .selectAll(".node") .data(nodes) .enter() .append("g") .attr("class", "node") .attr("transform", function (d) {
return "translate(" + d.y + "," + d.x + ")"; }) .on("click", (d) => {
console.log(`----------click------------`); }) .on("mouseover", () => {
console.log(`----------hover------------`); });
3.3.2 你的树图不简单—— radio tide tree
- d3.tree()传入参数不同
- link对角线生成器不同
- 节点transform设置不同
| 差别 | tide tree | radio tide tree |
|---|---|---|
| d3.tree()传入参数不同 | [width,height] | [radian,radius] |
| link对角线生成器不同 | linkHorizontal()或者 | linkRadial() |
| 节点transform设置不同 | x,y坐标 | 极坐标 |
// 2、生成树状布局,设置树图布局容器尺寸。 let tree = d3 .tree() .size([2 * Math.PI, 140]) .separation(function (a, b) {
return (a.parent == b.parent ? 1 : 2) / a.depth; }); let root = d3.hierarchy(this.treeData); tree(root);
link对角线生成器的不同,linkRadial()
// 4.2生成连线。 let link = svg .selectAll(".link") .data(links) // .enter() // .append("path") .join('path') .attr("class", "link") .attr('fill','none') .attr('stroke','#ccc') .attr('stroke-width','1.5px') .attr( "d", d3 .linkRadial() .angle(function (d) {
return d.x; }) .radius(function (d) {
return d.y; }) );
节点transform设置不同,极坐标的方式设置
// 4.3生成节点。 // 极坐标 function radialPoint(x, y) {
return [(y = +y) * Math.cos((x -= Math.PI / 2)), y * Math.sin(x)]; } let node = svg .selectAll(".node") .data(nodes) .enter() .append("g") .attr("class", "node") .attr("stroke", "red") .attr("transform", d => ` rotate(${
d.x * 180 / Math.PI - 90}) translate(${
d.y},0) `) // return "translate(" + radialPoint(d.x, d.y) + ")";
此处可上滑与tide tree代码进行对比,观察不同
3.3.3 更多可能——更多类型的树图
D3js 官网:https://d3js.org/
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/232229.html原文链接:https://javaforall.net
